| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 1 | //===--- ParseDeclCXX.cpp - C++ Declaration 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. | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | //  This file implements the C++ Declaration portions of the Parser interfaces. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
| Anders Carlsson | 0c6139d | 2009-06-27 00:27:47 +0000 | [diff] [blame] | 14 | #include "clang/Basic/OperatorKinds.h" | 
| Douglas Gregor | 1b7f898 | 2008-04-14 00:13:42 +0000 | [diff] [blame] | 15 | #include "clang/Parse/Parser.h" | 
| Chris Lattner | 500d329 | 2009-01-29 05:15:15 +0000 | [diff] [blame] | 16 | #include "clang/Parse/ParseDiagnostic.h" | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 17 | #include "clang/Parse/DeclSpec.h" | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 18 | #include "clang/Parse/Scope.h" | 
| Chris Lattner | bc8d564 | 2008-12-18 01:12:00 +0000 | [diff] [blame] | 19 | #include "ExtensionRAIIObject.h" | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 20 | using namespace clang; | 
 | 21 |  | 
 | 22 | /// ParseNamespace - We know that the current token is a namespace keyword. This | 
 | 23 | /// may either be a top level namespace or a block-level namespace alias. | 
 | 24 | /// | 
 | 25 | ///       namespace-definition: [C++ 7.3: basic.namespace] | 
 | 26 | ///         named-namespace-definition | 
 | 27 | ///         unnamed-namespace-definition | 
 | 28 | /// | 
 | 29 | ///       unnamed-namespace-definition: | 
 | 30 | ///         'namespace' attributes[opt] '{' namespace-body '}' | 
 | 31 | /// | 
 | 32 | ///       named-namespace-definition: | 
 | 33 | ///         original-namespace-definition | 
 | 34 | ///         extension-namespace-definition | 
 | 35 | /// | 
 | 36 | ///       original-namespace-definition: | 
 | 37 | ///         'namespace' identifier attributes[opt] '{' namespace-body '}' | 
 | 38 | /// | 
 | 39 | ///       extension-namespace-definition: | 
 | 40 | ///         'namespace' original-namespace-name '{' namespace-body '}' | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 41 | /// | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 42 | ///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias] | 
 | 43 | ///         'namespace' identifier '=' qualified-namespace-specifier ';' | 
 | 44 | /// | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 45 | Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context, | 
 | 46 |                                          SourceLocation &DeclEnd) { | 
| Chris Lattner | 04d6666 | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 47 |   assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 48 |   SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 49 |  | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 50 |   SourceLocation IdentLoc; | 
 | 51 |   IdentifierInfo *Ident = 0; | 
| Douglas Gregor | 6a588dd | 2009-06-17 19:49:00 +0000 | [diff] [blame] | 52 |  | 
 | 53 |   Token attrTok; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 54 |  | 
| Chris Lattner | 04d6666 | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 55 |   if (Tok.is(tok::identifier)) { | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 56 |     Ident = Tok.getIdentifierInfo(); | 
 | 57 |     IdentLoc = ConsumeToken();  // eat the identifier. | 
 | 58 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 59 |  | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 60 |   // Read label attributes, if present. | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 61 |   Action::AttrTy *AttrList = 0; | 
| Douglas Gregor | 6a588dd | 2009-06-17 19:49:00 +0000 | [diff] [blame] | 62 |   if (Tok.is(tok::kw___attribute)) { | 
 | 63 |     attrTok = Tok; | 
 | 64 |  | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 65 |     // FIXME: save these somewhere. | 
 | 66 |     AttrList = ParseAttributes(); | 
| Douglas Gregor | 6a588dd | 2009-06-17 19:49:00 +0000 | [diff] [blame] | 67 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 68 |  | 
| Douglas Gregor | 6a588dd | 2009-06-17 19:49:00 +0000 | [diff] [blame] | 69 |   if (Tok.is(tok::equal)) { | 
 | 70 |     if (AttrList) | 
 | 71 |       Diag(attrTok, diag::err_unexpected_namespace_attributes_alias); | 
 | 72 |  | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 73 |     return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); | 
| Douglas Gregor | 6a588dd | 2009-06-17 19:49:00 +0000 | [diff] [blame] | 74 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 75 |  | 
| Chris Lattner | 5144832 | 2009-03-29 14:02:43 +0000 | [diff] [blame] | 76 |   if (Tok.isNot(tok::l_brace)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 77 |     Diag(Tok, Ident ? diag::err_expected_lbrace : | 
| Chris Lattner | 5144832 | 2009-03-29 14:02:43 +0000 | [diff] [blame] | 78 |          diag::err_expected_ident_lbrace); | 
 | 79 |     return DeclPtrTy(); | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 80 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 81 |  | 
| Chris Lattner | 5144832 | 2009-03-29 14:02:43 +0000 | [diff] [blame] | 82 |   SourceLocation LBrace = ConsumeBrace(); | 
 | 83 |  | 
 | 84 |   // Enter a scope for the namespace. | 
 | 85 |   ParseScope NamespaceScope(this, Scope::DeclScope); | 
 | 86 |  | 
 | 87 |   DeclPtrTy NamespcDecl = | 
 | 88 |     Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace); | 
 | 89 |  | 
 | 90 |   PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions, | 
 | 91 |                                         PP.getSourceManager(), | 
 | 92 |                                         "parsing namespace"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 93 |  | 
| Chris Lattner | 5144832 | 2009-03-29 14:02:43 +0000 | [diff] [blame] | 94 |   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) | 
 | 95 |     ParseExternalDeclaration(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 96 |  | 
| Chris Lattner | 5144832 | 2009-03-29 14:02:43 +0000 | [diff] [blame] | 97 |   // Leave the namespace scope. | 
 | 98 |   NamespaceScope.Exit(); | 
 | 99 |  | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 100 |   SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace); | 
 | 101 |   Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); | 
| Chris Lattner | 5144832 | 2009-03-29 14:02:43 +0000 | [diff] [blame] | 102 |  | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 103 |   DeclEnd = RBraceLoc; | 
| Chris Lattner | 5144832 | 2009-03-29 14:02:43 +0000 | [diff] [blame] | 104 |   return NamespcDecl; | 
| Chris Lattner | 8f08cb7 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 105 | } | 
| Chris Lattner | c6fdc34 | 2008-01-12 07:05:38 +0000 | [diff] [blame] | 106 |  | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 107 | /// ParseNamespaceAlias - Parse the part after the '=' in a namespace | 
 | 108 | /// alias definition. | 
 | 109 | /// | 
| Anders Carlsson | 03bd5a1 | 2009-03-28 22:53:22 +0000 | [diff] [blame] | 110 | Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 111 |                                               SourceLocation AliasLoc, | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 112 |                                               IdentifierInfo *Alias, | 
 | 113 |                                               SourceLocation &DeclEnd) { | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 114 |   assert(Tok.is(tok::equal) && "Not equal token"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 115 |  | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 116 |   ConsumeToken(); // eat the '='. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 117 |  | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 118 |   CXXScopeSpec SS; | 
 | 119 |   // Parse (optional) nested-name-specifier. | 
| Douglas Gregor | 2dd078a | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 120 |   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false); | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 121 |  | 
 | 122 |   if (SS.isInvalid() || Tok.isNot(tok::identifier)) { | 
 | 123 |     Diag(Tok, diag::err_expected_namespace_name); | 
 | 124 |     // Skip to end of the definition and eat the ';'. | 
 | 125 |     SkipUntil(tok::semi); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 126 |     return DeclPtrTy(); | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 127 |   } | 
 | 128 |  | 
 | 129 |   // Parse identifier. | 
| Anders Carlsson | 03bd5a1 | 2009-03-28 22:53:22 +0000 | [diff] [blame] | 130 |   IdentifierInfo *Ident = Tok.getIdentifierInfo(); | 
 | 131 |   SourceLocation IdentLoc = ConsumeToken(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 132 |  | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 133 |   // Eat the ';'. | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 134 |   DeclEnd = Tok.getLocation(); | 
| Chris Lattner | 6869d8e | 2009-06-14 00:07:48 +0000 | [diff] [blame] | 135 |   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name, | 
 | 136 |                    "", tok::semi); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 137 |  | 
 | 138 |   return Actions.ActOnNamespaceAliasDef(CurScope, NamespaceLoc, AliasLoc, Alias, | 
| Anders Carlsson | 03bd5a1 | 2009-03-28 22:53:22 +0000 | [diff] [blame] | 139 |                                         SS, IdentLoc, Ident); | 
| Anders Carlsson | f67606a | 2009-03-28 04:07:16 +0000 | [diff] [blame] | 140 | } | 
 | 141 |  | 
| Chris Lattner | c6fdc34 | 2008-01-12 07:05:38 +0000 | [diff] [blame] | 142 | /// ParseLinkage - We know that the current token is a string_literal | 
 | 143 | /// and just before that, that extern was seen. | 
 | 144 | /// | 
 | 145 | ///       linkage-specification: [C++ 7.5p2: dcl.link] | 
 | 146 | ///         'extern' string-literal '{' declaration-seq[opt] '}' | 
 | 147 | ///         'extern' string-literal declaration | 
 | 148 | /// | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 149 | Parser::DeclPtrTy Parser::ParseLinkage(unsigned Context) { | 
| Douglas Gregor | c19923d | 2008-11-21 16:10:08 +0000 | [diff] [blame] | 150 |   assert(Tok.is(tok::string_literal) && "Not a string literal!"); | 
| Chris Lattner | c6fdc34 | 2008-01-12 07:05:38 +0000 | [diff] [blame] | 151 |   llvm::SmallVector<char, 8> LangBuffer; | 
 | 152 |   // LangBuffer is guaranteed to be big enough. | 
 | 153 |   LangBuffer.resize(Tok.getLength()); | 
 | 154 |   const char *LangBufPtr = &LangBuffer[0]; | 
 | 155 |   unsigned StrSize = PP.getSpelling(Tok, LangBufPtr); | 
 | 156 |  | 
 | 157 |   SourceLocation Loc = ConsumeStringToken(); | 
| Chris Lattner | c6fdc34 | 2008-01-12 07:05:38 +0000 | [diff] [blame] | 158 |  | 
| Douglas Gregor | 074149e | 2009-01-05 19:45:36 +0000 | [diff] [blame] | 159 |   ParseScope LinkageScope(this, Scope::DeclScope); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 160 |   DeclPtrTy LinkageSpec | 
 | 161 |     = Actions.ActOnStartLinkageSpecification(CurScope, | 
| Douglas Gregor | 074149e | 2009-01-05 19:45:36 +0000 | [diff] [blame] | 162 |                                              /*FIXME: */SourceLocation(), | 
 | 163 |                                              Loc, LangBufPtr, StrSize, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 164 |                                        Tok.is(tok::l_brace)? Tok.getLocation() | 
| Douglas Gregor | 074149e | 2009-01-05 19:45:36 +0000 | [diff] [blame] | 165 |                                                            : SourceLocation()); | 
 | 166 |  | 
 | 167 |   if (Tok.isNot(tok::l_brace)) { | 
 | 168 |     ParseDeclarationOrFunctionDefinition(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 169 |     return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, | 
| Douglas Gregor | 074149e | 2009-01-05 19:45:36 +0000 | [diff] [blame] | 170 |                                                    SourceLocation()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 171 |   } | 
| Douglas Gregor | f44515a | 2008-12-16 22:23:02 +0000 | [diff] [blame] | 172 |  | 
 | 173 |   SourceLocation LBrace = ConsumeBrace(); | 
| Douglas Gregor | f44515a | 2008-12-16 22:23:02 +0000 | [diff] [blame] | 174 |   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { | 
| Douglas Gregor | 074149e | 2009-01-05 19:45:36 +0000 | [diff] [blame] | 175 |     ParseExternalDeclaration(); | 
| Chris Lattner | c6fdc34 | 2008-01-12 07:05:38 +0000 | [diff] [blame] | 176 |   } | 
 | 177 |  | 
| Douglas Gregor | f44515a | 2008-12-16 22:23:02 +0000 | [diff] [blame] | 178 |   SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); | 
| Douglas Gregor | 074149e | 2009-01-05 19:45:36 +0000 | [diff] [blame] | 179 |   return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, RBrace); | 
| Chris Lattner | c6fdc34 | 2008-01-12 07:05:38 +0000 | [diff] [blame] | 180 | } | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 181 |  | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 182 | /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or | 
 | 183 | /// using-directive. Assumes that current token is 'using'. | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 184 | Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, | 
 | 185 |                                                      SourceLocation &DeclEnd) { | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 186 |   assert(Tok.is(tok::kw_using) && "Not using token"); | 
 | 187 |  | 
 | 188 |   // Eat 'using'. | 
 | 189 |   SourceLocation UsingLoc = ConsumeToken(); | 
 | 190 |  | 
| Chris Lattner | 2f27477 | 2009-01-06 06:55:51 +0000 | [diff] [blame] | 191 |   if (Tok.is(tok::kw_namespace)) | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 192 |     // Next token after 'using' is 'namespace' so it must be using-directive | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 193 |     return ParseUsingDirective(Context, UsingLoc, DeclEnd); | 
| Chris Lattner | 2f27477 | 2009-01-06 06:55:51 +0000 | [diff] [blame] | 194 |  | 
 | 195 |   // Otherwise, it must be using-declaration. | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 196 |   return ParseUsingDeclaration(Context, UsingLoc, DeclEnd); | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 197 | } | 
 | 198 |  | 
 | 199 | /// ParseUsingDirective - Parse C++ using-directive, assumes | 
 | 200 | /// that current token is 'namespace' and 'using' was already parsed. | 
 | 201 | /// | 
 | 202 | ///       using-directive: [C++ 7.3.p4: namespace.udir] | 
 | 203 | ///        'using' 'namespace' ::[opt] nested-name-specifier[opt] | 
 | 204 | ///                 namespace-name ; | 
 | 205 | /// [GNU] using-directive: | 
 | 206 | ///        'using' 'namespace' ::[opt] nested-name-specifier[opt] | 
 | 207 | ///                 namespace-name attributes[opt] ; | 
 | 208 | /// | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 209 | Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context, | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 210 |                                               SourceLocation UsingLoc, | 
 | 211 |                                               SourceLocation &DeclEnd) { | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 212 |   assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token"); | 
 | 213 |  | 
 | 214 |   // Eat 'namespace'. | 
 | 215 |   SourceLocation NamespcLoc = ConsumeToken(); | 
 | 216 |  | 
 | 217 |   CXXScopeSpec SS; | 
 | 218 |   // Parse (optional) nested-name-specifier. | 
| Douglas Gregor | 2dd078a | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 219 |   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false); | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 220 |  | 
 | 221 |   AttributeList *AttrList = 0; | 
 | 222 |   IdentifierInfo *NamespcName = 0; | 
 | 223 |   SourceLocation IdentLoc = SourceLocation(); | 
 | 224 |  | 
 | 225 |   // Parse namespace-name. | 
| Chris Lattner | 823c44e | 2009-01-06 07:27:21 +0000 | [diff] [blame] | 226 |   if (SS.isInvalid() || Tok.isNot(tok::identifier)) { | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 227 |     Diag(Tok, diag::err_expected_namespace_name); | 
 | 228 |     // If there was invalid namespace name, skip to end of decl, and eat ';'. | 
 | 229 |     SkipUntil(tok::semi); | 
 | 230 |     // FIXME: Are there cases, when we would like to call ActOnUsingDirective? | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 231 |     return DeclPtrTy(); | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 232 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 233 |  | 
| Chris Lattner | 823c44e | 2009-01-06 07:27:21 +0000 | [diff] [blame] | 234 |   // Parse identifier. | 
 | 235 |   NamespcName = Tok.getIdentifierInfo(); | 
 | 236 |   IdentLoc = ConsumeToken(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 237 |  | 
| Chris Lattner | 823c44e | 2009-01-06 07:27:21 +0000 | [diff] [blame] | 238 |   // Parse (optional) attributes (most likely GNU strong-using extension). | 
 | 239 |   if (Tok.is(tok::kw___attribute)) | 
 | 240 |     AttrList = ParseAttributes(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 241 |  | 
| Chris Lattner | 823c44e | 2009-01-06 07:27:21 +0000 | [diff] [blame] | 242 |   // Eat ';'. | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 243 |   DeclEnd = Tok.getLocation(); | 
| Chris Lattner | 6869d8e | 2009-06-14 00:07:48 +0000 | [diff] [blame] | 244 |   ExpectAndConsume(tok::semi, | 
 | 245 |                    AttrList ? diag::err_expected_semi_after_attribute_list : | 
 | 246 |                    diag::err_expected_semi_after_namespace_name, "", tok::semi); | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 247 |  | 
 | 248 |   return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS, | 
| Chris Lattner | 823c44e | 2009-01-06 07:27:21 +0000 | [diff] [blame] | 249 |                                       IdentLoc, NamespcName, AttrList); | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 250 | } | 
 | 251 |  | 
 | 252 | /// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that | 
 | 253 | /// 'using' was already seen. | 
 | 254 | /// | 
 | 255 | ///     using-declaration: [C++ 7.3.p3: namespace.udecl] | 
 | 256 | ///       'using' 'typename'[opt] ::[opt] nested-name-specifier | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 257 | ///               unqualified-id | 
 | 258 | ///       'using' :: unqualified-id | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 259 | /// | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 260 | Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 261 |                                                 SourceLocation UsingLoc, | 
| Anders Carlsson | 595adc1 | 2009-08-29 19:54:19 +0000 | [diff] [blame] | 262 |                                                 SourceLocation &DeclEnd, | 
 | 263 |                                                 AccessSpecifier AS) { | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 264 |   CXXScopeSpec SS; | 
 | 265 |   bool IsTypeName; | 
 | 266 |  | 
 | 267 |   // Ignore optional 'typename'. | 
 | 268 |   if (Tok.is(tok::kw_typename)) { | 
 | 269 |     ConsumeToken(); | 
 | 270 |     IsTypeName = true; | 
 | 271 |   } | 
 | 272 |   else | 
 | 273 |     IsTypeName = false; | 
 | 274 |  | 
 | 275 |   // Parse nested-name-specifier. | 
| Douglas Gregor | 2dd078a | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 276 |   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false); | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 277 |  | 
 | 278 |   AttributeList *AttrList = 0; | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 279 |  | 
 | 280 |   // Check nested-name specifier. | 
 | 281 |   if (SS.isInvalid()) { | 
 | 282 |     SkipUntil(tok::semi); | 
 | 283 |     return DeclPtrTy(); | 
 | 284 |   } | 
 | 285 |   if (Tok.is(tok::annot_template_id)) { | 
| Anders Carlsson | 73b39cf | 2009-08-28 03:35:18 +0000 | [diff] [blame] | 286 |     // C++0x N2914 [namespace.udecl]p5: | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 287 |     // A using-declaration shall not name a template-id. | 
| Anders Carlsson | 73b39cf | 2009-08-28 03:35:18 +0000 | [diff] [blame] | 288 |     Diag(Tok, diag::err_using_decl_can_not_refer_to_template_spec); | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 289 |     SkipUntil(tok::semi); | 
 | 290 |     return DeclPtrTy(); | 
 | 291 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 292 |  | 
| Anders Carlsson | 0c6139d | 2009-06-27 00:27:47 +0000 | [diff] [blame] | 293 |   IdentifierInfo *TargetName = 0; | 
 | 294 |   OverloadedOperatorKind Op = OO_None; | 
 | 295 |   SourceLocation IdentLoc; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 296 |  | 
| Anders Carlsson | 0c6139d | 2009-06-27 00:27:47 +0000 | [diff] [blame] | 297 |   if (Tok.is(tok::kw_operator)) { | 
 | 298 |     IdentLoc = Tok.getLocation(); | 
 | 299 |  | 
 | 300 |     Op = TryParseOperatorFunctionId(); | 
 | 301 |     if (!Op) { | 
 | 302 |       // If there was an invalid operator, skip to end of decl, and eat ';'. | 
 | 303 |       SkipUntil(tok::semi); | 
 | 304 |       return DeclPtrTy(); | 
 | 305 |     } | 
 | 306 |   } else if (Tok.is(tok::identifier)) { | 
 | 307 |     // Parse identifier. | 
 | 308 |     TargetName = Tok.getIdentifierInfo(); | 
 | 309 |     IdentLoc = ConsumeToken(); | 
 | 310 |   } else { | 
 | 311 |     // FIXME: Use a better diagnostic here. | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 312 |     Diag(Tok, diag::err_expected_ident_in_using); | 
| Anders Carlsson | 0c6139d | 2009-06-27 00:27:47 +0000 | [diff] [blame] | 313 |  | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 314 |     // If there was invalid identifier, skip to end of decl, and eat ';'. | 
 | 315 |     SkipUntil(tok::semi); | 
 | 316 |     return DeclPtrTy(); | 
 | 317 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 318 |  | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 319 |   // Parse (optional) attributes (most likely GNU strong-using extension). | 
 | 320 |   if (Tok.is(tok::kw___attribute)) | 
 | 321 |     AttrList = ParseAttributes(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 322 |  | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 323 |   // Eat ';'. | 
 | 324 |   DeclEnd = Tok.getLocation(); | 
 | 325 |   ExpectAndConsume(tok::semi, diag::err_expected_semi_after, | 
 | 326 |                    AttrList ? "attributes list" : "namespace name", tok::semi); | 
 | 327 |  | 
| Anders Carlsson | 595adc1 | 2009-08-29 19:54:19 +0000 | [diff] [blame] | 328 |   return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, | 
| Anders Carlsson | 0c6139d | 2009-06-27 00:27:47 +0000 | [diff] [blame] | 329 |                                        IdentLoc, TargetName, Op, | 
 | 330 |                                        AttrList, IsTypeName); | 
| Douglas Gregor | f780abc | 2008-12-30 03:27:21 +0000 | [diff] [blame] | 331 | } | 
 | 332 |  | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 333 | /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion. | 
 | 334 | /// | 
 | 335 | ///      static_assert-declaration: | 
 | 336 | ///        static_assert ( constant-expression  ,  string-literal  ) ; | 
 | 337 | /// | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 338 | Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 339 |   assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration"); | 
 | 340 |   SourceLocation StaticAssertLoc = ConsumeToken(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 341 |  | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 342 |   if (Tok.isNot(tok::l_paren)) { | 
 | 343 |     Diag(Tok, diag::err_expected_lparen); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 344 |     return DeclPtrTy(); | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 345 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 346 |  | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 347 |   SourceLocation LParenLoc = ConsumeParen(); | 
| Douglas Gregor | e0762c9 | 2009-06-19 23:52:42 +0000 | [diff] [blame] | 348 |  | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 349 |   OwningExprResult AssertExpr(ParseConstantExpression()); | 
 | 350 |   if (AssertExpr.isInvalid()) { | 
 | 351 |     SkipUntil(tok::semi); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 352 |     return DeclPtrTy(); | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 353 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 354 |  | 
| Anders Carlsson | ad5f960 | 2009-03-13 23:29:20 +0000 | [diff] [blame] | 355 |   if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi)) | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 356 |     return DeclPtrTy(); | 
| Anders Carlsson | ad5f960 | 2009-03-13 23:29:20 +0000 | [diff] [blame] | 357 |  | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 358 |   if (Tok.isNot(tok::string_literal)) { | 
 | 359 |     Diag(Tok, diag::err_expected_string_literal); | 
 | 360 |     SkipUntil(tok::semi); | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 361 |     return DeclPtrTy(); | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 362 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 363 |  | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 364 |   OwningExprResult AssertMessage(ParseStringLiteralExpression()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 365 |   if (AssertMessage.isInvalid()) | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 366 |     return DeclPtrTy(); | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 367 |  | 
| Anders Carlsson | 94b15fb | 2009-03-15 18:44:04 +0000 | [diff] [blame] | 368 |   MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 369 |  | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 370 |   DeclEnd = Tok.getLocation(); | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 371 |   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert); | 
 | 372 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 373 |   return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr), | 
| Anders Carlsson | 94b15fb | 2009-03-15 18:44:04 +0000 | [diff] [blame] | 374 |                                               move(AssertMessage)); | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 375 | } | 
 | 376 |  | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 377 | /// ParseDecltypeSpecifier - Parse a C++0x decltype specifier. | 
 | 378 | /// | 
 | 379 | /// 'decltype' ( expression ) | 
 | 380 | /// | 
 | 381 | void Parser::ParseDecltypeSpecifier(DeclSpec &DS) { | 
 | 382 |   assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier"); | 
 | 383 |  | 
 | 384 |   SourceLocation StartLoc = ConsumeToken(); | 
 | 385 |   SourceLocation LParenLoc = Tok.getLocation(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 386 |  | 
 | 387 |   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 388 |                        "decltype")) { | 
 | 389 |     SkipUntil(tok::r_paren); | 
 | 390 |     return; | 
 | 391 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 392 |  | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 393 |   // Parse the expression | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 394 |  | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 395 |   // C++0x [dcl.type.simple]p4: | 
 | 396 |   //   The operand of the decltype specifier is an unevaluated operand. | 
 | 397 |   EnterExpressionEvaluationContext Unevaluated(Actions, | 
 | 398 |                                                Action::Unevaluated); | 
 | 399 |   OwningExprResult Result = ParseExpression(); | 
 | 400 |   if (Result.isInvalid()) { | 
 | 401 |     SkipUntil(tok::r_paren); | 
 | 402 |     return; | 
 | 403 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 404 |  | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 405 |   // Match the ')' | 
 | 406 |   SourceLocation RParenLoc; | 
 | 407 |   if (Tok.is(tok::r_paren)) | 
 | 408 |     RParenLoc = ConsumeParen(); | 
 | 409 |   else | 
 | 410 |     MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 411 |  | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 412 |   if (RParenLoc.isInvalid()) | 
 | 413 |     return; | 
 | 414 |  | 
 | 415 |   const char *PrevSpec = 0; | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 416 |   unsigned DiagID; | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 417 |   // Check for duplicate type specifiers (e.g. "int decltype(a)"). | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 418 |   if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec, | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 419 |                          DiagID, Result.release())) | 
 | 420 |     Diag(StartLoc, DiagID) << PrevSpec; | 
| Anders Carlsson | 6fd634f | 2009-06-24 17:47:40 +0000 | [diff] [blame] | 421 | } | 
 | 422 |  | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 423 | /// ParseClassName - Parse a C++ class-name, which names a class. Note | 
 | 424 | /// that we only check that the result names a type; semantic analysis | 
 | 425 | /// will need to verify that the type names a class. The result is | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 426 | /// either a type or NULL, depending on whether a type name was | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 427 | /// found. | 
 | 428 | /// | 
 | 429 | ///       class-name: [C++ 9.1] | 
 | 430 | ///         identifier | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 431 | ///         simple-template-id | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 432 | /// | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 433 | Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, | 
| Fariborz Jahanian | d33c868 | 2009-07-20 17:43:15 +0000 | [diff] [blame] | 434 |                                           const CXXScopeSpec *SS, | 
 | 435 |                                           bool DestrExpected) { | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 436 |   // Check whether we have a template-id that names a type. | 
 | 437 |   if (Tok.is(tok::annot_template_id)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 438 |     TemplateIdAnnotation *TemplateId | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 439 |       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); | 
| Douglas Gregor | c45c232 | 2009-03-31 00:43:58 +0000 | [diff] [blame] | 440 |     if (TemplateId->Kind == TNK_Type_template) { | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 441 |       AnnotateTemplateIdTokenAsType(SS); | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 442 |  | 
 | 443 |       assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); | 
 | 444 |       TypeTy *Type = Tok.getAnnotationValue(); | 
 | 445 |       EndLocation = Tok.getAnnotationEndLoc(); | 
 | 446 |       ConsumeToken(); | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 447 |  | 
 | 448 |       if (Type) | 
 | 449 |         return Type; | 
 | 450 |       return true; | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 451 |     } | 
 | 452 |  | 
 | 453 |     // Fall through to produce an error below. | 
 | 454 |   } | 
 | 455 |  | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 456 |   if (Tok.isNot(tok::identifier)) { | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 457 |     Diag(Tok, diag::err_expected_class_name); | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 458 |     return true; | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 459 |   } | 
 | 460 |  | 
 | 461 |   // We have an identifier; check whether it is actually a type. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 462 |   TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(), | 
| Douglas Gregor | 42c39f3 | 2009-08-26 18:27:52 +0000 | [diff] [blame] | 463 |                                      Tok.getLocation(), CurScope, SS, | 
 | 464 |                                      true); | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 465 |   if (!Type) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 466 |     Diag(Tok, DestrExpected ? diag::err_destructor_class_name | 
| Fariborz Jahanian | d33c868 | 2009-07-20 17:43:15 +0000 | [diff] [blame] | 467 |                             : diag::err_expected_class_name); | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 468 |     return true; | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 469 |   } | 
 | 470 |  | 
 | 471 |   // Consume the identifier. | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 472 |   EndLocation = ConsumeToken(); | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 473 |   return Type; | 
 | 474 | } | 
 | 475 |  | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 476 | /// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or | 
 | 477 | /// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which | 
 | 478 | /// until we reach the start of a definition or see a token that | 
 | 479 | /// cannot start a definition. | 
 | 480 | /// | 
 | 481 | ///       class-specifier: [C++ class] | 
 | 482 | ///         class-head '{' member-specification[opt] '}' | 
 | 483 | ///         class-head '{' member-specification[opt] '}' attributes[opt] | 
 | 484 | ///       class-head: | 
 | 485 | ///         class-key identifier[opt] base-clause[opt] | 
 | 486 | ///         class-key nested-name-specifier identifier base-clause[opt] | 
 | 487 | ///         class-key nested-name-specifier[opt] simple-template-id | 
 | 488 | ///                          base-clause[opt] | 
 | 489 | /// [GNU]   class-key attributes[opt] identifier[opt] base-clause[opt] | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 490 | /// [GNU]   class-key attributes[opt] nested-name-specifier | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 491 | ///                          identifier base-clause[opt] | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 492 | /// [GNU]   class-key attributes[opt] nested-name-specifier[opt] | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 493 | ///                          simple-template-id base-clause[opt] | 
 | 494 | ///       class-key: | 
 | 495 | ///         'class' | 
 | 496 | ///         'struct' | 
 | 497 | ///         'union' | 
 | 498 | /// | 
 | 499 | ///       elaborated-type-specifier: [C++ dcl.type.elab] | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 500 | ///         class-key ::[opt] nested-name-specifier[opt] identifier | 
 | 501 | ///         class-key ::[opt] nested-name-specifier[opt] 'template'[opt] | 
 | 502 | ///                          simple-template-id | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 503 | /// | 
 | 504 | ///  Note that the C++ class-specifier and elaborated-type-specifier, | 
 | 505 | ///  together, subsume the C99 struct-or-union-specifier: | 
 | 506 | /// | 
 | 507 | ///       struct-or-union-specifier: [C99 6.7.2.1] | 
 | 508 | ///         struct-or-union identifier[opt] '{' struct-contents '}' | 
 | 509 | ///         struct-or-union identifier | 
 | 510 | /// [GNU]   struct-or-union attributes[opt] identifier[opt] '{' struct-contents | 
 | 511 | ///                                                         '}' attributes[opt] | 
 | 512 | /// [GNU]   struct-or-union attributes[opt] identifier | 
 | 513 | ///       struct-or-union: | 
 | 514 | ///         'struct' | 
 | 515 | ///         'union' | 
| Chris Lattner | 4c97d76 | 2009-04-12 21:49:30 +0000 | [diff] [blame] | 516 | void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, | 
 | 517 |                                  SourceLocation StartLoc, DeclSpec &DS, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 518 |                                  const ParsedTemplateInfo &TemplateInfo, | 
| Douglas Gregor | 06c0fec | 2009-03-25 22:00:53 +0000 | [diff] [blame] | 519 |                                  AccessSpecifier AS) { | 
| Chris Lattner | 4c97d76 | 2009-04-12 21:49:30 +0000 | [diff] [blame] | 520 |   DeclSpec::TST TagType; | 
 | 521 |   if (TagTokKind == tok::kw_struct) | 
 | 522 |     TagType = DeclSpec::TST_struct; | 
 | 523 |   else if (TagTokKind == tok::kw_class) | 
 | 524 |     TagType = DeclSpec::TST_class; | 
 | 525 |   else { | 
 | 526 |     assert(TagTokKind == tok::kw_union && "Not a class specifier"); | 
 | 527 |     TagType = DeclSpec::TST_union; | 
 | 528 |   } | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 529 |  | 
 | 530 |   AttributeList *Attr = 0; | 
 | 531 |   // If attributes exist after tag, parse them. | 
 | 532 |   if (Tok.is(tok::kw___attribute)) | 
 | 533 |     Attr = ParseAttributes(); | 
 | 534 |  | 
| Steve Naroff | f59e17e | 2008-12-24 20:59:21 +0000 | [diff] [blame] | 535 |   // If declspecs exist after tag, parse them. | 
| Eli Friedman | 290eeb0 | 2009-06-08 23:27:34 +0000 | [diff] [blame] | 536 |   if (Tok.is(tok::kw___declspec)) | 
 | 537 |     Attr = ParseMicrosoftDeclSpec(Attr); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 538 |  | 
| Douglas Gregor | b117a60 | 2009-09-04 05:53:02 +0000 | [diff] [blame] | 539 |   if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) { | 
 | 540 |     // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but | 
 | 541 |     // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 542 |     // token sequence "struct __is_pod", make __is_pod into a normal | 
| Douglas Gregor | b117a60 | 2009-09-04 05:53:02 +0000 | [diff] [blame] | 543 |     // identifier rather than a keyword, to allow libstdc++ 4.2 to work | 
 | 544 |     // properly. | 
 | 545 |     Tok.getIdentifierInfo()->setTokenID(tok::identifier); | 
 | 546 |     Tok.setKind(tok::identifier); | 
 | 547 |   } | 
 | 548 |  | 
 | 549 |   if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) { | 
 | 550 |     // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but | 
 | 551 |     // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 552 |     // token sequence "struct __is_empty", make __is_empty into a normal | 
| Douglas Gregor | b117a60 | 2009-09-04 05:53:02 +0000 | [diff] [blame] | 553 |     // identifier rather than a keyword, to allow libstdc++ 4.2 to work | 
 | 554 |     // properly. | 
 | 555 |     Tok.getIdentifierInfo()->setTokenID(tok::identifier); | 
 | 556 |     Tok.setKind(tok::identifier); | 
 | 557 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 558 |  | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 559 |   // Parse the (optional) nested-name-specifier. | 
 | 560 |   CXXScopeSpec SS; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 561 |   if (getLang().CPlusPlus && | 
| Douglas Gregor | 2dd078a | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 562 |       ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 563 |     if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 564 |       Diag(Tok, diag::err_expected_ident); | 
| Douglas Gregor | cc63668 | 2009-02-17 23:15:12 +0000 | [diff] [blame] | 565 |  | 
 | 566 |   // Parse the (optional) class name or simple-template-id. | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 567 |   IdentifierInfo *Name = 0; | 
 | 568 |   SourceLocation NameLoc; | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 569 |   TemplateIdAnnotation *TemplateId = 0; | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 570 |   if (Tok.is(tok::identifier)) { | 
 | 571 |     Name = Tok.getIdentifierInfo(); | 
 | 572 |     NameLoc = ConsumeToken(); | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 573 |   } else if (Tok.is(tok::annot_template_id)) { | 
 | 574 |     TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); | 
 | 575 |     NameLoc = ConsumeToken(); | 
| Douglas Gregor | cc63668 | 2009-02-17 23:15:12 +0000 | [diff] [blame] | 576 |  | 
| Douglas Gregor | c45c232 | 2009-03-31 00:43:58 +0000 | [diff] [blame] | 577 |     if (TemplateId->Kind != TNK_Type_template) { | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 578 |       // The template-name in the simple-template-id refers to | 
 | 579 |       // something other than a class template. Give an appropriate | 
 | 580 |       // error message and skip to the ';'. | 
 | 581 |       SourceRange Range(NameLoc); | 
 | 582 |       if (SS.isNotEmpty()) | 
 | 583 |         Range.setBegin(SS.getBeginLoc()); | 
| Douglas Gregor | cc63668 | 2009-02-17 23:15:12 +0000 | [diff] [blame] | 584 |  | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 585 |       Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template) | 
 | 586 |         << Name << static_cast<int>(TemplateId->Kind) << Range; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 587 |  | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 588 |       DS.SetTypeSpecError(); | 
 | 589 |       SkipUntil(tok::semi, false, true); | 
 | 590 |       TemplateId->Destroy(); | 
 | 591 |       return; | 
| Douglas Gregor | cc63668 | 2009-02-17 23:15:12 +0000 | [diff] [blame] | 592 |     } | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 593 |   } | 
 | 594 |  | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 595 |   // There are four options here.  If we have 'struct foo;', then this | 
 | 596 |   // is either a forward declaration or a friend declaration, which | 
 | 597 |   // have to be treated differently.  If we have 'struct foo {...' or | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 598 |   // 'struct foo :...' then this is a definition. Otherwise we have | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 599 |   // something like 'struct foo xyz', a reference. | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 600 |   Action::TagUseKind TUK; | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 601 |   if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))) | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 602 |     TUK = Action::TUK_Definition; | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 603 |   else if (Tok.is(tok::semi)) | 
 | 604 |     TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration; | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 605 |   else | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 606 |     TUK = Action::TUK_Reference; | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 607 |  | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 608 |   if (!Name && !TemplateId && TUK != Action::TUK_Definition) { | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 609 |     // We have a declaration or reference to an anonymous class. | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 610 |     Diag(StartLoc, diag::err_anon_type_definition) | 
 | 611 |       << DeclSpec::getSpecifierName(TagType); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 612 |  | 
 | 613 |     // Skip the rest of this declarator, up until the comma or semicolon. | 
 | 614 |     SkipUntil(tok::comma, true); | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 615 |  | 
 | 616 |     if (TemplateId) | 
 | 617 |       TemplateId->Destroy(); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 618 |     return; | 
 | 619 |   } | 
 | 620 |  | 
| Douglas Gregor | ddc29e1 | 2009-02-06 22:42:48 +0000 | [diff] [blame] | 621 |   // Create the tag portion of the class or class template. | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 622 |   Action::DeclResult TagOrTempResult = true; // invalid | 
 | 623 |   Action::TypeResult TypeResult = true; // invalid | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 624 |   TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; | 
 | 625 |  | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 626 |   // FIXME: When TUK == TUK_Reference and we have a template-id, we need | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 627 |   // to turn that template-id into a type. | 
 | 628 |  | 
| Douglas Gregor | 402abb5 | 2009-05-28 23:31:59 +0000 | [diff] [blame] | 629 |   bool Owned = false; | 
| John McCall | f1bbbb4 | 2009-09-04 01:14:41 +0000 | [diff] [blame] | 630 |   if (TemplateId) { | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 631 |     // Explicit specialization, class template partial specialization, | 
 | 632 |     // or explicit instantiation. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 633 |     ASTTemplateArgsPtr TemplateArgsPtr(Actions, | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 634 |                                        TemplateId->getTemplateArgs(), | 
 | 635 |                                        TemplateId->getTemplateArgIsType(), | 
 | 636 |                                        TemplateId->NumArgs); | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 637 |     if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 638 |         TUK == Action::TUK_Declaration) { | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 639 |       // This is an explicit instantiation of a class template. | 
 | 640 |       TagOrTempResult | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 641 |         = Actions.ActOnExplicitInstantiation(CurScope, | 
| Douglas Gregor | 45f9655 | 2009-09-04 06:33:52 +0000 | [diff] [blame] | 642 |                                              TemplateInfo.ExternLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 643 |                                              TemplateInfo.TemplateLoc, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 644 |                                              TagType, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 645 |                                              StartLoc, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 646 |                                              SS, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 647 |                                      TemplateTy::make(TemplateId->Template), | 
 | 648 |                                              TemplateId->TemplateNameLoc, | 
 | 649 |                                              TemplateId->LAngleLoc, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 650 |                                              TemplateArgsPtr, | 
 | 651 |                                       TemplateId->getTemplateArgLocations(), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 652 |                                              TemplateId->RAngleLoc, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 653 |                                              Attr); | 
| John McCall | f1bbbb4 | 2009-09-04 01:14:41 +0000 | [diff] [blame] | 654 |     } else if (TUK == Action::TUK_Reference || TUK == Action::TUK_Friend) { | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 655 |       TypeResult | 
| John McCall | 6b2becf | 2009-09-08 17:47:29 +0000 | [diff] [blame] | 656 |         = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template), | 
 | 657 |                                       TemplateId->TemplateNameLoc, | 
 | 658 |                                       TemplateId->LAngleLoc, | 
 | 659 |                                       TemplateArgsPtr, | 
 | 660 |                                       TemplateId->getTemplateArgLocations(), | 
 | 661 |                                       TemplateId->RAngleLoc); | 
 | 662 |  | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 663 |       TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK, | 
 | 664 |                                                   TagType, StartLoc); | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 665 |     } else { | 
 | 666 |       // This is an explicit specialization or a class template | 
 | 667 |       // partial specialization. | 
 | 668 |       TemplateParameterLists FakedParamLists; | 
 | 669 |  | 
 | 670 |       if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { | 
 | 671 |         // This looks like an explicit instantiation, because we have | 
 | 672 |         // something like | 
 | 673 |         // | 
 | 674 |         //   template class Foo<X> | 
 | 675 |         // | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 676 |         // but it actually has a definition. Most likely, this was | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 677 |         // meant to be an explicit specialization, but the user forgot | 
 | 678 |         // the '<>' after 'template'. | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 679 |         assert(TUK == Action::TUK_Definition && "Expected a definition here"); | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 680 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 681 |         SourceLocation LAngleLoc | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 682 |           = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 683 |         Diag(TemplateId->TemplateNameLoc, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 684 |              diag::err_explicit_instantiation_with_definition) | 
 | 685 |           << SourceRange(TemplateInfo.TemplateLoc) | 
 | 686 |           << CodeModificationHint::CreateInsertion(LAngleLoc, "<>"); | 
 | 687 |  | 
 | 688 |         // Create a fake template parameter list that contains only | 
 | 689 |         // "template<>", so that we treat this construct as a class | 
 | 690 |         // template specialization. | 
 | 691 |         FakedParamLists.push_back( | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 692 |           Actions.ActOnTemplateParameterList(0, SourceLocation(), | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 693 |                                              TemplateInfo.TemplateLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 694 |                                              LAngleLoc, | 
 | 695 |                                              0, 0, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 696 |                                              LAngleLoc)); | 
 | 697 |         TemplateParams = &FakedParamLists; | 
 | 698 |       } | 
 | 699 |  | 
 | 700 |       // Build the class template specialization. | 
 | 701 |       TagOrTempResult | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 702 |         = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TUK, | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 703 |                        StartLoc, SS, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 704 |                        TemplateTy::make(TemplateId->Template), | 
 | 705 |                        TemplateId->TemplateNameLoc, | 
 | 706 |                        TemplateId->LAngleLoc, | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 707 |                        TemplateArgsPtr, | 
 | 708 |                        TemplateId->getTemplateArgLocations(), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 709 |                        TemplateId->RAngleLoc, | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 710 |                        Attr, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 711 |                        Action::MultiTemplateParamsArg(Actions, | 
| Douglas Gregor | cc63668 | 2009-02-17 23:15:12 +0000 | [diff] [blame] | 712 |                                     TemplateParams? &(*TemplateParams)[0] : 0, | 
 | 713 |                                  TemplateParams? TemplateParams->size() : 0)); | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 714 |     } | 
| Douglas Gregor | 39a8de1 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 715 |     TemplateId->Destroy(); | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 716 |   } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 717 |              TUK == Action::TUK_Declaration) { | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 718 |     // Explicit instantiation of a member of a class template | 
 | 719 |     // specialization, e.g., | 
 | 720 |     // | 
 | 721 |     //   template struct Outer<int>::Inner; | 
 | 722 |     // | 
 | 723 |     TagOrTempResult | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 724 |       = Actions.ActOnExplicitInstantiation(CurScope, | 
| Douglas Gregor | 45f9655 | 2009-09-04 06:33:52 +0000 | [diff] [blame] | 725 |                                            TemplateInfo.ExternLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 726 |                                            TemplateInfo.TemplateLoc, | 
 | 727 |                                            TagType, StartLoc, SS, Name, | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 728 |                                            NameLoc, Attr); | 
 | 729 |   } else { | 
 | 730 |     if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 731 |         TUK == Action::TUK_Definition) { | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 732 |       // FIXME: Diagnose this particular error. | 
 | 733 |     } | 
 | 734 |  | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 735 |     bool IsDependent = false; | 
 | 736 |  | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 737 |     // Declaration or definition of a class type | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 738 |     TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS, | 
| Douglas Gregor | 7cdbc58 | 2009-07-22 23:48:44 +0000 | [diff] [blame] | 739 |                                        Name, NameLoc, Attr, AS, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 740 |                                   Action::MultiTemplateParamsArg(Actions, | 
| Douglas Gregor | 7cdbc58 | 2009-07-22 23:48:44 +0000 | [diff] [blame] | 741 |                                     TemplateParams? &(*TemplateParams)[0] : 0, | 
 | 742 |                                     TemplateParams? TemplateParams->size() : 0), | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 743 |                                        Owned, IsDependent); | 
 | 744 |  | 
 | 745 |     // If ActOnTag said the type was dependent, try again with the | 
 | 746 |     // less common call. | 
 | 747 |     if (IsDependent) | 
 | 748 |       TypeResult = Actions.ActOnDependentTag(CurScope, TagType, TUK, | 
 | 749 |                                              SS, Name, StartLoc, NameLoc);       | 
| Douglas Gregor | 3f5b61c | 2009-05-14 00:28:11 +0000 | [diff] [blame] | 750 |   } | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 751 |  | 
 | 752 |   // Parse the optional base clause (C++ only). | 
| Chris Lattner | 22bd905 | 2009-02-16 22:07:16 +0000 | [diff] [blame] | 753 |   if (getLang().CPlusPlus && Tok.is(tok::colon)) | 
| Douglas Gregor | 212e81c | 2009-03-25 00:13:59 +0000 | [diff] [blame] | 754 |     ParseBaseClause(TagOrTempResult.get()); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 755 |  | 
 | 756 |   // If there is a body, parse it and inform the actions module. | 
 | 757 |   if (Tok.is(tok::l_brace)) | 
| Argyrios Kyrtzidis | 0795232 | 2008-07-01 10:37:29 +0000 | [diff] [blame] | 758 |     if (getLang().CPlusPlus) | 
| Douglas Gregor | 212e81c | 2009-03-25 00:13:59 +0000 | [diff] [blame] | 759 |       ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get()); | 
| Argyrios Kyrtzidis | 0795232 | 2008-07-01 10:37:29 +0000 | [diff] [blame] | 760 |     else | 
| Douglas Gregor | 212e81c | 2009-03-25 00:13:59 +0000 | [diff] [blame] | 761 |       ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); | 
| John McCall | 0f434ec | 2009-07-31 02:45:11 +0000 | [diff] [blame] | 762 |   else if (TUK == Action::TUK_Definition) { | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 763 |     // FIXME: Complain that we have a base-specifier list but no | 
 | 764 |     // definition. | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 765 |     Diag(Tok, diag::err_expected_lbrace); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 766 |   } | 
 | 767 |  | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 768 |   void *Result; | 
 | 769 |   if (!TypeResult.isInvalid()) { | 
 | 770 |     TagType = DeclSpec::TST_typename; | 
 | 771 |     Result = TypeResult.get(); | 
 | 772 |     Owned = false; | 
 | 773 |   } else if (!TagOrTempResult.isInvalid()) { | 
 | 774 |     Result = TagOrTempResult.get().getAs<void>(); | 
 | 775 |   } else { | 
| Douglas Gregor | ddc29e1 | 2009-02-06 22:42:48 +0000 | [diff] [blame] | 776 |     DS.SetTypeSpecError(); | 
| Anders Carlsson | 66e9977 | 2009-05-11 22:27:47 +0000 | [diff] [blame] | 777 |     return; | 
 | 778 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 779 |  | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 780 |   const char *PrevSpec = 0; | 
 | 781 |   unsigned DiagID; | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 782 |  | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 783 |   if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, DiagID, | 
| John McCall | c4e7019 | 2009-09-11 04:59:25 +0000 | [diff] [blame] | 784 |                          Result, Owned)) | 
| John McCall | fec5401 | 2009-08-03 20:12:06 +0000 | [diff] [blame] | 785 |     Diag(StartLoc, DiagID) << PrevSpec; | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 786 | } | 
 | 787 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 788 | /// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived]. | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 789 | /// | 
 | 790 | ///       base-clause : [C++ class.derived] | 
 | 791 | ///         ':' base-specifier-list | 
 | 792 | ///       base-specifier-list: | 
 | 793 | ///         base-specifier '...'[opt] | 
 | 794 | ///         base-specifier-list ',' base-specifier '...'[opt] | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 795 | void Parser::ParseBaseClause(DeclPtrTy ClassDecl) { | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 796 |   assert(Tok.is(tok::colon) && "Not a base clause"); | 
 | 797 |   ConsumeToken(); | 
 | 798 |  | 
| Douglas Gregor | f8268ae | 2008-10-22 17:49:05 +0000 | [diff] [blame] | 799 |   // Build up an array of parsed base specifiers. | 
 | 800 |   llvm::SmallVector<BaseTy *, 8> BaseInfo; | 
 | 801 |  | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 802 |   while (true) { | 
 | 803 |     // Parse a base-specifier. | 
| Douglas Gregor | f8268ae | 2008-10-22 17:49:05 +0000 | [diff] [blame] | 804 |     BaseResult Result = ParseBaseSpecifier(ClassDecl); | 
| Douglas Gregor | 5ac8aff | 2009-01-26 22:44:13 +0000 | [diff] [blame] | 805 |     if (Result.isInvalid()) { | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 806 |       // Skip the rest of this base specifier, up until the comma or | 
 | 807 |       // opening brace. | 
| Douglas Gregor | f8268ae | 2008-10-22 17:49:05 +0000 | [diff] [blame] | 808 |       SkipUntil(tok::comma, tok::l_brace, true, true); | 
 | 809 |     } else { | 
 | 810 |       // Add this to our array of base specifiers. | 
| Douglas Gregor | 5ac8aff | 2009-01-26 22:44:13 +0000 | [diff] [blame] | 811 |       BaseInfo.push_back(Result.get()); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 812 |     } | 
 | 813 |  | 
 | 814 |     // If the next token is a comma, consume it and keep reading | 
 | 815 |     // base-specifiers. | 
 | 816 |     if (Tok.isNot(tok::comma)) break; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 817 |  | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 818 |     // Consume the comma. | 
 | 819 |     ConsumeToken(); | 
 | 820 |   } | 
| Douglas Gregor | f8268ae | 2008-10-22 17:49:05 +0000 | [diff] [blame] | 821 |  | 
 | 822 |   // Attach the base specifiers | 
| Jay Foad | beaaccd | 2009-05-21 09:52:38 +0000 | [diff] [blame] | 823 |   Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo.data(), BaseInfo.size()); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 824 | } | 
 | 825 |  | 
 | 826 | /// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is | 
 | 827 | /// one entry in the base class list of a class specifier, for example: | 
 | 828 | ///    class foo : public bar, virtual private baz { | 
 | 829 | /// 'public bar' and 'virtual private baz' are each base-specifiers. | 
 | 830 | /// | 
 | 831 | ///       base-specifier: [C++ class.derived] | 
 | 832 | ///         ::[opt] nested-name-specifier[opt] class-name | 
 | 833 | ///         'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt] | 
 | 834 | ///                        class-name | 
 | 835 | ///         access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt] | 
 | 836 | ///                        class-name | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 837 | Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) { | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 838 |   bool IsVirtual = false; | 
 | 839 |   SourceLocation StartLoc = Tok.getLocation(); | 
 | 840 |  | 
 | 841 |   // Parse the 'virtual' keyword. | 
 | 842 |   if (Tok.is(tok::kw_virtual))  { | 
 | 843 |     ConsumeToken(); | 
 | 844 |     IsVirtual = true; | 
 | 845 |   } | 
 | 846 |  | 
 | 847 |   // Parse an (optional) access specifier. | 
 | 848 |   AccessSpecifier Access = getAccessSpecifierIfPresent(); | 
 | 849 |   if (Access) | 
 | 850 |     ConsumeToken(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 851 |  | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 852 |   // Parse the 'virtual' keyword (again!), in case it came after the | 
 | 853 |   // access specifier. | 
 | 854 |   if (Tok.is(tok::kw_virtual))  { | 
 | 855 |     SourceLocation VirtualLoc = ConsumeToken(); | 
 | 856 |     if (IsVirtual) { | 
 | 857 |       // Complain about duplicate 'virtual' | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 858 |       Diag(VirtualLoc, diag::err_dup_virtual) | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 859 |         << CodeModificationHint::CreateRemoval(SourceRange(VirtualLoc)); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 860 |     } | 
 | 861 |  | 
 | 862 |     IsVirtual = true; | 
 | 863 |   } | 
 | 864 |  | 
| Argyrios Kyrtzidis | eb83ecd | 2008-11-08 16:45:02 +0000 | [diff] [blame] | 865 |   // Parse optional '::' and optional nested-name-specifier. | 
 | 866 |   CXXScopeSpec SS; | 
| Douglas Gregor | 2dd078a | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 867 |   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 868 |  | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 869 |   // The location of the base class itself. | 
 | 870 |   SourceLocation BaseLoc = Tok.getLocation(); | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 871 |  | 
 | 872 |   // Parse the class-name. | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 873 |   SourceLocation EndLocation; | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 874 |   TypeResult BaseType = ParseClassName(EndLocation, &SS); | 
 | 875 |   if (BaseType.isInvalid()) | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 876 |     return true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 877 |  | 
 | 878 |   // Find the complete source range for the base-specifier. | 
| Douglas Gregor | 7f43d67 | 2009-02-25 23:52:28 +0000 | [diff] [blame] | 879 |   SourceRange Range(StartLoc, EndLocation); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 880 |  | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 881 |   // Notify semantic analysis that we have parsed a complete | 
 | 882 |   // base-specifier. | 
| Sebastian Redl | a55e52c | 2008-11-25 22:21:31 +0000 | [diff] [blame] | 883 |   return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, | 
| Douglas Gregor | 31a19b6 | 2009-04-01 21:51:26 +0000 | [diff] [blame] | 884 |                                     BaseType.get(), BaseLoc); | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 885 | } | 
 | 886 |  | 
 | 887 | /// getAccessSpecifierIfPresent - Determine whether the next token is | 
 | 888 | /// a C++ access-specifier. | 
 | 889 | /// | 
 | 890 | ///       access-specifier: [C++ class.derived] | 
 | 891 | ///         'private' | 
 | 892 | ///         'protected' | 
 | 893 | ///         'public' | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 894 | AccessSpecifier Parser::getAccessSpecifierIfPresent() const { | 
| Douglas Gregor | e37ac4f | 2008-04-13 21:30:24 +0000 | [diff] [blame] | 895 |   switch (Tok.getKind()) { | 
 | 896 |   default: return AS_none; | 
 | 897 |   case tok::kw_private: return AS_private; | 
 | 898 |   case tok::kw_protected: return AS_protected; | 
 | 899 |   case tok::kw_public: return AS_public; | 
 | 900 |   } | 
 | 901 | } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 902 |  | 
| Eli Friedman | d33133c | 2009-07-22 21:45:50 +0000 | [diff] [blame] | 903 | void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, | 
 | 904 |                                              DeclPtrTy ThisDecl) { | 
 | 905 |   // We just declared a member function. If this member function | 
 | 906 |   // has any default arguments, we'll need to parse them later. | 
 | 907 |   LateParsedMethodDeclaration *LateMethod = 0; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 908 |   DeclaratorChunk::FunctionTypeInfo &FTI | 
| Eli Friedman | d33133c | 2009-07-22 21:45:50 +0000 | [diff] [blame] | 909 |     = DeclaratorInfo.getTypeObject(0).Fun; | 
 | 910 |   for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) { | 
 | 911 |     if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) { | 
 | 912 |       if (!LateMethod) { | 
 | 913 |         // Push this method onto the stack of late-parsed method | 
 | 914 |         // declarations. | 
 | 915 |         getCurrentClass().MethodDecls.push_back( | 
 | 916 |                                 LateParsedMethodDeclaration(ThisDecl)); | 
 | 917 |         LateMethod = &getCurrentClass().MethodDecls.back(); | 
| Douglas Gregor | d83d040 | 2009-08-22 00:34:47 +0000 | [diff] [blame] | 918 |         LateMethod->TemplateScope = CurScope->isTemplateParamScope(); | 
| Eli Friedman | d33133c | 2009-07-22 21:45:50 +0000 | [diff] [blame] | 919 |  | 
 | 920 |         // Add all of the parameters prior to this one (they don't | 
 | 921 |         // have default arguments). | 
 | 922 |         LateMethod->DefaultArgs.reserve(FTI.NumArgs); | 
 | 923 |         for (unsigned I = 0; I < ParamIdx; ++I) | 
 | 924 |           LateMethod->DefaultArgs.push_back( | 
 | 925 |                     LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param)); | 
 | 926 |       } | 
 | 927 |  | 
 | 928 |       // Add this parameter to the list of parameters (it or may | 
 | 929 |       // not have a default argument). | 
 | 930 |       LateMethod->DefaultArgs.push_back( | 
 | 931 |         LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param, | 
 | 932 |                                   FTI.ArgInfo[ParamIdx].DefaultArgTokens)); | 
 | 933 |     } | 
 | 934 |   } | 
 | 935 | } | 
 | 936 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 937 | /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. | 
 | 938 | /// | 
 | 939 | ///       member-declaration: | 
 | 940 | ///         decl-specifier-seq[opt] member-declarator-list[opt] ';' | 
 | 941 | ///         function-definition ';'[opt] | 
 | 942 | ///         ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO] | 
 | 943 | ///         using-declaration                                            [TODO] | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 944 | /// [C++0x] static_assert-declaration | 
| Anders Carlsson | 5aeccdb | 2009-03-26 00:52:18 +0000 | [diff] [blame] | 945 | ///         template-declaration | 
| Chris Lattner | bc8d564 | 2008-12-18 01:12:00 +0000 | [diff] [blame] | 946 | /// [GNU]   '__extension__' member-declaration | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 947 | /// | 
 | 948 | ///       member-declarator-list: | 
 | 949 | ///         member-declarator | 
 | 950 | ///         member-declarator-list ',' member-declarator | 
 | 951 | /// | 
 | 952 | ///       member-declarator: | 
 | 953 | ///         declarator pure-specifier[opt] | 
 | 954 | ///         declarator constant-initializer[opt] | 
 | 955 | ///         identifier[opt] ':' constant-expression | 
 | 956 | /// | 
| Sebastian Redl | e2b6833 | 2009-04-12 17:16:29 +0000 | [diff] [blame] | 957 | ///       pure-specifier: | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 958 | ///         '= 0' | 
 | 959 | /// | 
 | 960 | ///       constant-initializer: | 
 | 961 | ///         '=' constant-expression | 
 | 962 | /// | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 963 | void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, | 
 | 964 |                                        const ParsedTemplateInfo &TemplateInfo) { | 
| Anders Carlsson | 511d7ab | 2009-03-11 16:27:10 +0000 | [diff] [blame] | 965 |   // static_assert-declaration | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 966 |   if (Tok.is(tok::kw_static_assert)) { | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 967 |     // FIXME: Check for templates | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 968 |     SourceLocation DeclEnd; | 
 | 969 |     ParseStaticAssertDeclaration(DeclEnd); | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 970 |     return; | 
 | 971 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 972 |  | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 973 |   if (Tok.is(tok::kw_template)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 974 |     assert(!TemplateInfo.TemplateParams && | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 975 |            "Nested template improperly parsed?"); | 
| Chris Lattner | 97144fc | 2009-04-02 04:16:50 +0000 | [diff] [blame] | 976 |     SourceLocation DeclEnd; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 977 |     ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd, | 
| Douglas Gregor | 4d9a16f | 2009-05-12 23:25:50 +0000 | [diff] [blame] | 978 |                                          AS); | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 979 |     return; | 
 | 980 |   } | 
| Anders Carlsson | 5aeccdb | 2009-03-26 00:52:18 +0000 | [diff] [blame] | 981 |  | 
| Chris Lattner | bc8d564 | 2008-12-18 01:12:00 +0000 | [diff] [blame] | 982 |   // Handle:  member-declaration ::= '__extension__' member-declaration | 
 | 983 |   if (Tok.is(tok::kw___extension__)) { | 
 | 984 |     // __extension__ silences extension warnings in the subexpression. | 
 | 985 |     ExtensionRAIIObject O(Diags);  // Use RAII to do this. | 
 | 986 |     ConsumeToken(); | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 987 |     return ParseCXXClassMemberDeclaration(AS, TemplateInfo); | 
| Chris Lattner | bc8d564 | 2008-12-18 01:12:00 +0000 | [diff] [blame] | 988 |   } | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 989 |  | 
 | 990 |   if (Tok.is(tok::kw_using)) { | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 991 |     // FIXME: Check for template aliases | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 992 |  | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 993 |     // Eat 'using'. | 
 | 994 |     SourceLocation UsingLoc = ConsumeToken(); | 
 | 995 |  | 
 | 996 |     if (Tok.is(tok::kw_namespace)) { | 
 | 997 |       Diag(UsingLoc, diag::err_using_namespace_in_class); | 
 | 998 |       SkipUntil(tok::semi, true, true); | 
 | 999 |     } | 
 | 1000 |     else { | 
 | 1001 |       SourceLocation DeclEnd; | 
 | 1002 |       // Otherwise, it must be using-declaration. | 
| Anders Carlsson | 595adc1 | 2009-08-29 19:54:19 +0000 | [diff] [blame] | 1003 |       ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd, AS); | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 1004 |     } | 
 | 1005 |     return; | 
 | 1006 |   } | 
 | 1007 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1008 |   SourceLocation DSStart = Tok.getLocation(); | 
 | 1009 |   // decl-specifier-seq: | 
 | 1010 |   // Parse the common declaration-specifiers piece. | 
 | 1011 |   DeclSpec DS; | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 1012 |   ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1013 |  | 
 | 1014 |   if (Tok.is(tok::semi)) { | 
 | 1015 |     ConsumeToken(); | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 1016 |  | 
| Anders Carlsson | 4111181 | 2009-09-11 17:54:14 +0000 | [diff] [blame^] | 1017 |     if (DS.isFriendSpecified()) { | 
 | 1018 |       // FIXME: Friend templates are ignored for now. | 
 | 1019 |       if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) | 
 | 1020 |         return; | 
 | 1021 |        | 
| John McCall | 3f9a8a6 | 2009-08-11 06:59:38 +0000 | [diff] [blame] | 1022 |       Actions.ActOnFriendDecl(CurScope, &DS, /*IsDefinition*/ false); | 
| Anders Carlsson | 4111181 | 2009-09-11 17:54:14 +0000 | [diff] [blame^] | 1023 |     } else | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1024 |       Actions.ParsedFreeStandingDeclSpec(CurScope, DS); | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 1025 |  | 
 | 1026 |     return; | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1027 |   } | 
| Argyrios Kyrtzidis | 0795232 | 2008-07-01 10:37:29 +0000 | [diff] [blame] | 1028 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1029 |   Declarator DeclaratorInfo(DS, Declarator::MemberContext); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1030 |  | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1031 |   if (Tok.isNot(tok::colon)) { | 
 | 1032 |     // Parse the first declarator. | 
 | 1033 |     ParseDeclarator(DeclaratorInfo); | 
 | 1034 |     // Error parsing the declarator? | 
| Douglas Gregor | 10bd368 | 2008-11-17 22:58:34 +0000 | [diff] [blame] | 1035 |     if (!DeclaratorInfo.hasName()) { | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1036 |       // If so, skip until the semi-colon or a }. | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1037 |       SkipUntil(tok::r_brace, true); | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1038 |       if (Tok.is(tok::semi)) | 
 | 1039 |         ConsumeToken(); | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1040 |       return; | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1041 |     } | 
 | 1042 |  | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1043 |     // function-definition: | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1044 |     if (Tok.is(tok::l_brace) | 
| Sebastian Redl | d3a413d | 2009-04-26 20:35:05 +0000 | [diff] [blame] | 1045 |         || (DeclaratorInfo.isFunctionDeclarator() && | 
 | 1046 |             (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) { | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1047 |       if (!DeclaratorInfo.isFunctionDeclarator()) { | 
 | 1048 |         Diag(Tok, diag::err_func_def_no_params); | 
 | 1049 |         ConsumeBrace(); | 
 | 1050 |         SkipUntil(tok::r_brace, true); | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1051 |         return; | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1052 |       } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1053 |  | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1054 |       if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { | 
 | 1055 |         Diag(Tok, diag::err_function_declared_typedef); | 
 | 1056 |         // This recovery skips the entire function body. It would be nice | 
 | 1057 |         // to simply call ParseCXXInlineMethodDef() below, however Sema | 
 | 1058 |         // assumes the declarator represents a function, not a typedef. | 
 | 1059 |         ConsumeBrace(); | 
 | 1060 |         SkipUntil(tok::r_brace, true); | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1061 |         return; | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1062 |       } | 
 | 1063 |  | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 1064 |       ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo); | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1065 |       return; | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1066 |     } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1067 |   } | 
 | 1068 |  | 
 | 1069 |   // member-declarator-list: | 
 | 1070 |   //   member-declarator | 
 | 1071 |   //   member-declarator-list ',' member-declarator | 
 | 1072 |  | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1073 |   llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup; | 
| Sebastian Redl | 15faa7f | 2008-12-09 20:22:58 +0000 | [diff] [blame] | 1074 |   OwningExprResult BitfieldSize(Actions); | 
 | 1075 |   OwningExprResult Init(Actions); | 
| Sebastian Redl | e2b6833 | 2009-04-12 17:16:29 +0000 | [diff] [blame] | 1076 |   bool Deleted = false; | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1077 |  | 
 | 1078 |   while (1) { | 
 | 1079 |  | 
 | 1080 |     // member-declarator: | 
 | 1081 |     //   declarator pure-specifier[opt] | 
 | 1082 |     //   declarator constant-initializer[opt] | 
 | 1083 |     //   identifier[opt] ':' constant-expression | 
 | 1084 |  | 
 | 1085 |     if (Tok.is(tok::colon)) { | 
 | 1086 |       ConsumeToken(); | 
| Sebastian Redl | 0e9eabc | 2008-12-09 13:15:23 +0000 | [diff] [blame] | 1087 |       BitfieldSize = ParseConstantExpression(); | 
 | 1088 |       if (BitfieldSize.isInvalid()) | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1089 |         SkipUntil(tok::comma, true, true); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1090 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1091 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1092 |     // pure-specifier: | 
 | 1093 |     //   '= 0' | 
 | 1094 |     // | 
 | 1095 |     // constant-initializer: | 
 | 1096 |     //   '=' constant-expression | 
| Sebastian Redl | e2b6833 | 2009-04-12 17:16:29 +0000 | [diff] [blame] | 1097 |     // | 
 | 1098 |     // defaulted/deleted function-definition: | 
 | 1099 |     //   '=' 'default'                          [TODO] | 
 | 1100 |     //   '=' 'delete' | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1101 |  | 
 | 1102 |     if (Tok.is(tok::equal)) { | 
 | 1103 |       ConsumeToken(); | 
| Sebastian Redl | e2b6833 | 2009-04-12 17:16:29 +0000 | [diff] [blame] | 1104 |       if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) { | 
 | 1105 |         ConsumeToken(); | 
 | 1106 |         Deleted = true; | 
 | 1107 |       } else { | 
 | 1108 |         Init = ParseInitializer(); | 
 | 1109 |         if (Init.isInvalid()) | 
 | 1110 |           SkipUntil(tok::comma, true, true); | 
 | 1111 |       } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1112 |     } | 
 | 1113 |  | 
 | 1114 |     // If attributes exist after the declarator, parse them. | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 1115 |     if (Tok.is(tok::kw___attribute)) { | 
 | 1116 |       SourceLocation Loc; | 
 | 1117 |       AttributeList *AttrList = ParseAttributes(&Loc); | 
 | 1118 |       DeclaratorInfo.AddAttributes(AttrList, Loc); | 
 | 1119 |     } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1120 |  | 
| Argyrios Kyrtzidis | 0795232 | 2008-07-01 10:37:29 +0000 | [diff] [blame] | 1121 |     // NOTE: If Sema is the Action module and declarator is an instance field, | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1122 |     // this call will *not* return the created decl; It will return null. | 
| Argyrios Kyrtzidis | 0795232 | 2008-07-01 10:37:29 +0000 | [diff] [blame] | 1123 |     // See Sema::ActOnCXXMemberDeclarator for details. | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 1124 |  | 
 | 1125 |     DeclPtrTy ThisDecl; | 
 | 1126 |     if (DS.isFriendSpecified()) { | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 1127 |       // TODO: handle initializers, bitfields, 'delete', friend templates | 
| John McCall | 3f9a8a6 | 2009-08-11 06:59:38 +0000 | [diff] [blame] | 1128 |       ThisDecl = Actions.ActOnFriendDecl(CurScope, &DeclaratorInfo, | 
 | 1129 |                                          /*IsDefinition*/ false); | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 1130 |     } else { | 
 | 1131 |       Action::MultiTemplateParamsArg TemplateParams(Actions, | 
 | 1132 |           TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0, | 
 | 1133 |           TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0); | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 1134 |       ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS, | 
 | 1135 |                                                   DeclaratorInfo, | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 1136 |                                                   move(TemplateParams), | 
| John McCall | 67d1a67 | 2009-08-06 02:15:43 +0000 | [diff] [blame] | 1137 |                                                   BitfieldSize.release(), | 
 | 1138 |                                                   Init.release(), | 
 | 1139 |                                                   Deleted); | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 1140 |     } | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1141 |     if (ThisDecl) | 
 | 1142 |       DeclsInGroup.push_back(ThisDecl); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1143 |  | 
| Douglas Gregor | 72b505b | 2008-12-16 21:30:33 +0000 | [diff] [blame] | 1144 |     if (DeclaratorInfo.isFunctionDeclarator() && | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1145 |         DeclaratorInfo.getDeclSpec().getStorageClassSpec() | 
| Douglas Gregor | 72b505b | 2008-12-16 21:30:33 +0000 | [diff] [blame] | 1146 |           != DeclSpec::SCS_typedef) { | 
| Eli Friedman | d33133c | 2009-07-22 21:45:50 +0000 | [diff] [blame] | 1147 |       HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl); | 
| Douglas Gregor | 72b505b | 2008-12-16 21:30:33 +0000 | [diff] [blame] | 1148 |     } | 
 | 1149 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1150 |     // If we don't have a comma, it is either the end of the list (a ';') | 
 | 1151 |     // or an error, bail out. | 
 | 1152 |     if (Tok.isNot(tok::comma)) | 
 | 1153 |       break; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1154 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1155 |     // Consume the comma. | 
 | 1156 |     ConsumeToken(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1157 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1158 |     // Parse the next declarator. | 
 | 1159 |     DeclaratorInfo.clear(); | 
| Sebastian Redl | 15faa7f | 2008-12-09 20:22:58 +0000 | [diff] [blame] | 1160 |     BitfieldSize = 0; | 
 | 1161 |     Init = 0; | 
| Sebastian Redl | e2b6833 | 2009-04-12 17:16:29 +0000 | [diff] [blame] | 1162 |     Deleted = false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1163 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1164 |     // Attributes are only allowed on the second declarator. | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 1165 |     if (Tok.is(tok::kw___attribute)) { | 
 | 1166 |       SourceLocation Loc; | 
 | 1167 |       AttributeList *AttrList = ParseAttributes(&Loc); | 
 | 1168 |       DeclaratorInfo.AddAttributes(AttrList, Loc); | 
 | 1169 |     } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1170 |  | 
| Argyrios Kyrtzidis | 3a9fdb4 | 2008-06-28 08:10:48 +0000 | [diff] [blame] | 1171 |     if (Tok.isNot(tok::colon)) | 
 | 1172 |       ParseDeclarator(DeclaratorInfo); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1173 |   } | 
 | 1174 |  | 
 | 1175 |   if (Tok.is(tok::semi)) { | 
 | 1176 |     ConsumeToken(); | 
| Eli Friedman | c1dc653 | 2009-05-29 01:49:24 +0000 | [diff] [blame] | 1177 |     Actions.FinalizeDeclaratorGroup(CurScope, DS, DeclsInGroup.data(), | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1178 |                                     DeclsInGroup.size()); | 
 | 1179 |     return; | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1180 |   } | 
 | 1181 |  | 
 | 1182 |   Diag(Tok, diag::err_expected_semi_decl_list); | 
 | 1183 |   // Skip to end of block or statement | 
 | 1184 |   SkipUntil(tok::r_brace, true, true); | 
 | 1185 |   if (Tok.is(tok::semi)) | 
 | 1186 |     ConsumeToken(); | 
| Chris Lattner | 682bf92 | 2009-03-29 16:50:03 +0000 | [diff] [blame] | 1187 |   return; | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1188 | } | 
 | 1189 |  | 
 | 1190 | /// ParseCXXMemberSpecification - Parse the class definition. | 
 | 1191 | /// | 
 | 1192 | ///       member-specification: | 
 | 1193 | ///         member-declaration member-specification[opt] | 
 | 1194 | ///         access-specifier ':' member-specification[opt] | 
 | 1195 | /// | 
 | 1196 | void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1197 |                                          unsigned TagType, DeclPtrTy TagDecl) { | 
| Sanjiv Gupta | 31fc07d | 2008-10-31 09:52:39 +0000 | [diff] [blame] | 1198 |   assert((TagType == DeclSpec::TST_struct || | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1199 |          TagType == DeclSpec::TST_union  || | 
| Sanjiv Gupta | 31fc07d | 2008-10-31 09:52:39 +0000 | [diff] [blame] | 1200 |          TagType == DeclSpec::TST_class) && "Invalid TagType!"); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1201 |  | 
| Chris Lattner | 49f28ca | 2009-03-05 08:00:35 +0000 | [diff] [blame] | 1202 |   PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions, | 
 | 1203 |                                         PP.getSourceManager(), | 
 | 1204 |                                         "parsing struct/union/class body"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1205 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1206 |   SourceLocation LBraceLoc = ConsumeBrace(); | 
 | 1207 |  | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1208 |   // Determine whether this is a top-level (non-nested) class. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1209 |   bool TopLevelClass = ClassStack.empty() || | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1210 |     CurScope->isInCXXInlineMethodScope(); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1211 |  | 
 | 1212 |   // Enter a scope for the class. | 
| Douglas Gregor | 3218c4b | 2009-01-09 22:42:13 +0000 | [diff] [blame] | 1213 |   ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1214 |  | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1215 |   // Note that we are parsing a new (potentially-nested) class definition. | 
 | 1216 |   ParsingClassDefinition ParsingDef(*this, TagDecl, TopLevelClass); | 
 | 1217 |  | 
| Douglas Gregor | ddc29e1 | 2009-02-06 22:42:48 +0000 | [diff] [blame] | 1218 |   if (TagDecl) | 
 | 1219 |     Actions.ActOnTagStartDefinition(CurScope, TagDecl); | 
 | 1220 |   else { | 
 | 1221 |     SkipUntil(tok::r_brace, false, false); | 
 | 1222 |     return; | 
 | 1223 |   } | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1224 |  | 
 | 1225 |   // C++ 11p3: Members of a class defined with the keyword class are private | 
 | 1226 |   // by default. Members of a class defined with the keywords struct or union | 
 | 1227 |   // are public by default. | 
 | 1228 |   AccessSpecifier CurAS; | 
 | 1229 |   if (TagType == DeclSpec::TST_class) | 
 | 1230 |     CurAS = AS_private; | 
 | 1231 |   else | 
 | 1232 |     CurAS = AS_public; | 
 | 1233 |  | 
 | 1234 |   // While we still have something to read, read the member-declarations. | 
 | 1235 |   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { | 
 | 1236 |     // Each iteration of this loop reads one member-declaration. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1237 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1238 |     // Check for extraneous top-level semicolon. | 
 | 1239 |     if (Tok.is(tok::semi)) { | 
 | 1240 |       Diag(Tok, diag::ext_extra_struct_semi); | 
 | 1241 |       ConsumeToken(); | 
 | 1242 |       continue; | 
 | 1243 |     } | 
 | 1244 |  | 
 | 1245 |     AccessSpecifier AS = getAccessSpecifierIfPresent(); | 
 | 1246 |     if (AS != AS_none) { | 
 | 1247 |       // Current token is a C++ access specifier. | 
 | 1248 |       CurAS = AS; | 
 | 1249 |       ConsumeToken(); | 
 | 1250 |       ExpectAndConsume(tok::colon, diag::err_expected_colon); | 
 | 1251 |       continue; | 
 | 1252 |     } | 
 | 1253 |  | 
| Douglas Gregor | 37b372b | 2009-08-20 22:52:58 +0000 | [diff] [blame] | 1254 |     // FIXME: Make sure we don't have a template here. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1255 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1256 |     // Parse all the comma separated declarators. | 
 | 1257 |     ParseCXXClassMemberDeclaration(CurAS); | 
 | 1258 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1259 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1260 |   SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1261 |  | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1262 |   AttributeList *AttrList = 0; | 
 | 1263 |   // If attributes exist after class contents, parse them. | 
 | 1264 |   if (Tok.is(tok::kw___attribute)) | 
 | 1265 |     AttrList = ParseAttributes(); // FIXME: where should I put them? | 
 | 1266 |  | 
 | 1267 |   Actions.ActOnFinishCXXMemberSpecification(CurScope, RecordLoc, TagDecl, | 
 | 1268 |                                             LBraceLoc, RBraceLoc); | 
 | 1269 |  | 
 | 1270 |   // C++ 9.2p2: Within the class member-specification, the class is regarded as | 
 | 1271 |   // complete within function bodies, default arguments, | 
 | 1272 |   // exception-specifications, and constructor ctor-initializers (including | 
 | 1273 |   // such things in nested classes). | 
 | 1274 |   // | 
| Douglas Gregor | 72b505b | 2008-12-16 21:30:33 +0000 | [diff] [blame] | 1275 |   // FIXME: Only function bodies and constructor ctor-initializers are | 
 | 1276 |   // parsed correctly, fix the rest. | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1277 |   if (TopLevelClass) { | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1278 |     // We are not inside a nested class. This class and its nested classes | 
| Douglas Gregor | 72b505b | 2008-12-16 21:30:33 +0000 | [diff] [blame] | 1279 |     // are complete and we can parse the delayed portions of method | 
 | 1280 |     // declarations and the lexed inline method definitions. | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1281 |     ParseLexedMethodDeclarations(getCurrentClass()); | 
 | 1282 |     ParseLexedMethodDefs(getCurrentClass()); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1283 |   } | 
 | 1284 |  | 
 | 1285 |   // Leave the class scope. | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1286 |   ParsingDef.Pop(); | 
| Douglas Gregor | 8935b8b | 2008-12-10 06:34:36 +0000 | [diff] [blame] | 1287 |   ClassScope.Exit(); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1288 |  | 
| Argyrios Kyrtzidis | 07a5b28 | 2009-07-14 03:17:52 +0000 | [diff] [blame] | 1289 |   Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc); | 
| Argyrios Kyrtzidis | 4cc18a4 | 2008-06-24 22:12:16 +0000 | [diff] [blame] | 1290 | } | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1291 |  | 
 | 1292 | /// ParseConstructorInitializer - Parse a C++ constructor initializer, | 
 | 1293 | /// which explicitly initializes the members or base classes of a | 
 | 1294 | /// class (C++ [class.base.init]). For example, the three initializers | 
 | 1295 | /// after the ':' in the Derived constructor below: | 
 | 1296 | /// | 
 | 1297 | /// @code | 
 | 1298 | /// class Base { }; | 
 | 1299 | /// class Derived : Base { | 
 | 1300 | ///   int x; | 
 | 1301 | ///   float f; | 
 | 1302 | /// public: | 
 | 1303 | ///   Derived(float f) : Base(), x(17), f(f) { } | 
 | 1304 | /// }; | 
 | 1305 | /// @endcode | 
 | 1306 | /// | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1307 | /// [C++]  ctor-initializer: | 
 | 1308 | ///          ':' mem-initializer-list | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1309 | /// | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1310 | /// [C++]  mem-initializer-list: | 
 | 1311 | ///          mem-initializer | 
 | 1312 | ///          mem-initializer , mem-initializer-list | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1313 | void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) { | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1314 |   assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'"); | 
 | 1315 |  | 
 | 1316 |   SourceLocation ColonLoc = ConsumeToken(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1317 |  | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1318 |   llvm::SmallVector<MemInitTy*, 4> MemInitializers; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1319 |  | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1320 |   do { | 
 | 1321 |     MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); | 
| Douglas Gregor | 5ac8aff | 2009-01-26 22:44:13 +0000 | [diff] [blame] | 1322 |     if (!MemInit.isInvalid()) | 
 | 1323 |       MemInitializers.push_back(MemInit.get()); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1324 |  | 
 | 1325 |     if (Tok.is(tok::comma)) | 
 | 1326 |       ConsumeToken(); | 
 | 1327 |     else if (Tok.is(tok::l_brace)) | 
 | 1328 |       break; | 
 | 1329 |     else { | 
 | 1330 |       // Skip over garbage, until we get to '{'.  Don't eat the '{'. | 
| Sebastian Redl | d3a413d | 2009-04-26 20:35:05 +0000 | [diff] [blame] | 1331 |       Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1332 |       SkipUntil(tok::l_brace, true, true); | 
 | 1333 |       break; | 
 | 1334 |     } | 
 | 1335 |   } while (true); | 
 | 1336 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1337 |   Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, | 
| Jay Foad | beaaccd | 2009-05-21 09:52:38 +0000 | [diff] [blame] | 1338 |                                MemInitializers.data(), MemInitializers.size()); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1339 | } | 
 | 1340 |  | 
 | 1341 | /// ParseMemInitializer - Parse a C++ member initializer, which is | 
 | 1342 | /// part of a constructor initializer that explicitly initializes one | 
 | 1343 | /// member or base class (C++ [class.base.init]). See | 
 | 1344 | /// ParseConstructorInitializer for an example. | 
 | 1345 | /// | 
 | 1346 | /// [C++] mem-initializer: | 
 | 1347 | ///         mem-initializer-id '(' expression-list[opt] ')' | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1348 | /// | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1349 | /// [C++] mem-initializer-id: | 
 | 1350 | ///         '::'[opt] nested-name-specifier[opt] class-name | 
 | 1351 | ///         identifier | 
| Chris Lattner | b28317a | 2009-03-28 19:18:32 +0000 | [diff] [blame] | 1352 | Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) { | 
| Fariborz Jahanian | bcfad54 | 2009-06-30 23:26:25 +0000 | [diff] [blame] | 1353 |   // parse '::'[opt] nested-name-specifier[opt] | 
 | 1354 |   CXXScopeSpec SS; | 
| Douglas Gregor | 2dd078a | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 1355 |   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false); | 
| Fariborz Jahanian | 9617433 | 2009-07-01 19:21:19 +0000 | [diff] [blame] | 1356 |   TypeTy *TemplateTypeTy = 0; | 
 | 1357 |   if (Tok.is(tok::annot_template_id)) { | 
 | 1358 |     TemplateIdAnnotation *TemplateId | 
 | 1359 |       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); | 
 | 1360 |     if (TemplateId->Kind == TNK_Type_template) { | 
 | 1361 |       AnnotateTemplateIdTokenAsType(&SS); | 
 | 1362 |       assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); | 
 | 1363 |       TemplateTypeTy = Tok.getAnnotationValue(); | 
 | 1364 |     } | 
 | 1365 |     // FIXME. May need to check for TNK_Dependent_template as well. | 
 | 1366 |   } | 
 | 1367 |   if (!TemplateTypeTy && Tok.isNot(tok::identifier)) { | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 1368 |     Diag(Tok, diag::err_expected_member_or_base_name); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1369 |     return true; | 
 | 1370 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1371 |  | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1372 |   // Get the identifier. This may be a member name or a class name, | 
 | 1373 |   // but we'll let the semantic analysis determine which it is. | 
| Fariborz Jahanian | 9617433 | 2009-07-01 19:21:19 +0000 | [diff] [blame] | 1374 |   IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0; | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1375 |   SourceLocation IdLoc = ConsumeToken(); | 
 | 1376 |  | 
 | 1377 |   // Parse the '('. | 
 | 1378 |   if (Tok.isNot(tok::l_paren)) { | 
| Chris Lattner | 1ab3b96 | 2008-11-18 07:48:38 +0000 | [diff] [blame] | 1379 |     Diag(Tok, diag::err_expected_lparen); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1380 |     return true; | 
 | 1381 |   } | 
 | 1382 |   SourceLocation LParenLoc = ConsumeParen(); | 
 | 1383 |  | 
 | 1384 |   // Parse the optional expression-list. | 
| Sebastian Redl | a55e52c | 2008-11-25 22:21:31 +0000 | [diff] [blame] | 1385 |   ExprVector ArgExprs(Actions); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1386 |   CommaLocsTy CommaLocs; | 
 | 1387 |   if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { | 
 | 1388 |     SkipUntil(tok::r_paren); | 
 | 1389 |     return true; | 
 | 1390 |   } | 
 | 1391 |  | 
 | 1392 |   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
 | 1393 |  | 
| Fariborz Jahanian | 9617433 | 2009-07-01 19:21:19 +0000 | [diff] [blame] | 1394 |   return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, SS, II, | 
 | 1395 |                                      TemplateTypeTy, IdLoc, | 
| Sebastian Redl | a55e52c | 2008-11-25 22:21:31 +0000 | [diff] [blame] | 1396 |                                      LParenLoc, ArgExprs.take(), | 
| Jay Foad | beaaccd | 2009-05-21 09:52:38 +0000 | [diff] [blame] | 1397 |                                      ArgExprs.size(), CommaLocs.data(), | 
 | 1398 |                                      RParenLoc); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 1399 | } | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1400 |  | 
 | 1401 | /// ParseExceptionSpecification - Parse a C++ exception-specification | 
 | 1402 | /// (C++ [except.spec]). | 
 | 1403 | /// | 
| Douglas Gregor | a474561 | 2008-12-01 18:00:20 +0000 | [diff] [blame] | 1404 | ///       exception-specification: | 
 | 1405 | ///         'throw' '(' type-id-list [opt] ')' | 
 | 1406 | /// [MS]    'throw' '(' '...' ')' | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1407 | /// | 
| Douglas Gregor | a474561 | 2008-12-01 18:00:20 +0000 | [diff] [blame] | 1408 | ///       type-id-list: | 
 | 1409 | ///         type-id | 
 | 1410 | ///         type-id-list ',' type-id | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1411 | /// | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 1412 | bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc, | 
| Sebastian Redl | ef65f06 | 2009-05-29 18:02:33 +0000 | [diff] [blame] | 1413 |                                          llvm::SmallVector<TypeTy*, 2> | 
 | 1414 |                                              &Exceptions, | 
 | 1415 |                                          llvm::SmallVector<SourceRange, 2> | 
 | 1416 |                                              &Ranges, | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 1417 |                                          bool &hasAnyExceptionSpec) { | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1418 |   assert(Tok.is(tok::kw_throw) && "expected throw"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1419 |  | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1420 |   SourceLocation ThrowLoc = ConsumeToken(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1421 |  | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1422 |   if (!Tok.is(tok::l_paren)) { | 
 | 1423 |     return Diag(Tok, diag::err_expected_lparen_after) << "throw"; | 
 | 1424 |   } | 
 | 1425 |   SourceLocation LParenLoc = ConsumeParen(); | 
 | 1426 |  | 
| Douglas Gregor | a474561 | 2008-12-01 18:00:20 +0000 | [diff] [blame] | 1427 |   // Parse throw(...), a Microsoft extension that means "this function | 
 | 1428 |   // can throw anything". | 
 | 1429 |   if (Tok.is(tok::ellipsis)) { | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 1430 |     hasAnyExceptionSpec = true; | 
| Douglas Gregor | a474561 | 2008-12-01 18:00:20 +0000 | [diff] [blame] | 1431 |     SourceLocation EllipsisLoc = ConsumeToken(); | 
 | 1432 |     if (!getLang().Microsoft) | 
 | 1433 |       Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec); | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 1434 |     EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
| Douglas Gregor | a474561 | 2008-12-01 18:00:20 +0000 | [diff] [blame] | 1435 |     return false; | 
 | 1436 |   } | 
 | 1437 |  | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1438 |   // Parse the sequence of type-ids. | 
| Sebastian Redl | ef65f06 | 2009-05-29 18:02:33 +0000 | [diff] [blame] | 1439 |   SourceRange Range; | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1440 |   while (Tok.isNot(tok::r_paren)) { | 
| Sebastian Redl | ef65f06 | 2009-05-29 18:02:33 +0000 | [diff] [blame] | 1441 |     TypeResult Res(ParseTypeName(&Range)); | 
 | 1442 |     if (!Res.isInvalid()) { | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 1443 |       Exceptions.push_back(Res.get()); | 
| Sebastian Redl | ef65f06 | 2009-05-29 18:02:33 +0000 | [diff] [blame] | 1444 |       Ranges.push_back(Range); | 
 | 1445 |     } | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1446 |     if (Tok.is(tok::comma)) | 
 | 1447 |       ConsumeToken(); | 
| Sebastian Redl | 7dc8134 | 2009-04-29 17:30:04 +0000 | [diff] [blame] | 1448 |     else | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1449 |       break; | 
 | 1450 |   } | 
 | 1451 |  | 
| Sebastian Redl | ab197ba | 2009-02-09 18:23:29 +0000 | [diff] [blame] | 1452 |   EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); | 
| Douglas Gregor | 0fe7bea | 2008-11-25 03:22:00 +0000 | [diff] [blame] | 1453 |   return false; | 
 | 1454 | } | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1455 |  | 
 | 1456 | /// \brief We have just started parsing the definition of a new class, | 
 | 1457 | /// so push that class onto our stack of classes that is currently | 
 | 1458 | /// being parsed. | 
 | 1459 | void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool TopLevelClass) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1460 |   assert((TopLevelClass || !ClassStack.empty()) && | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1461 |          "Nested class without outer class"); | 
 | 1462 |   ClassStack.push(new ParsingClass(ClassDecl, TopLevelClass)); | 
 | 1463 | } | 
 | 1464 |  | 
 | 1465 | /// \brief Deallocate the given parsed class and all of its nested | 
 | 1466 | /// classes. | 
 | 1467 | void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) { | 
 | 1468 |   for (unsigned I = 0, N = Class->NestedClasses.size(); I != N; ++I) | 
 | 1469 |     DeallocateParsedClasses(Class->NestedClasses[I]); | 
 | 1470 |   delete Class; | 
 | 1471 | } | 
 | 1472 |  | 
 | 1473 | /// \brief Pop the top class of the stack of classes that are | 
 | 1474 | /// currently being parsed. | 
 | 1475 | /// | 
 | 1476 | /// This routine should be called when we have finished parsing the | 
 | 1477 | /// definition of a class, but have not yet popped the Scope | 
 | 1478 | /// associated with the class's definition. | 
 | 1479 | /// | 
 | 1480 | /// \returns true if the class we've popped is a top-level class, | 
 | 1481 | /// false otherwise. | 
 | 1482 | void Parser::PopParsingClass() { | 
 | 1483 |   assert(!ClassStack.empty() && "Mismatched push/pop for class parsing"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1484 |  | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1485 |   ParsingClass *Victim = ClassStack.top(); | 
 | 1486 |   ClassStack.pop(); | 
 | 1487 |   if (Victim->TopLevelClass) { | 
 | 1488 |     // Deallocate all of the nested classes of this class, | 
 | 1489 |     // recursively: we don't need to keep any of this information. | 
 | 1490 |     DeallocateParsedClasses(Victim); | 
 | 1491 |     return; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 1492 |   } | 
| Douglas Gregor | 6569d68 | 2009-05-27 23:11:45 +0000 | [diff] [blame] | 1493 |   assert(!ClassStack.empty() && "Missing top-level class?"); | 
 | 1494 |  | 
 | 1495 |   if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() && | 
 | 1496 |       Victim->NestedClasses.empty()) { | 
 | 1497 |     // The victim is a nested class, but we will not need to perform | 
 | 1498 |     // any processing after the definition of this class since it has | 
 | 1499 |     // no members whose handling was delayed. Therefore, we can just | 
 | 1500 |     // remove this nested class. | 
 | 1501 |     delete Victim; | 
 | 1502 |     return; | 
 | 1503 |   } | 
 | 1504 |  | 
 | 1505 |   // This nested class has some members that will need to be processed | 
 | 1506 |   // after the top-level class is completely defined. Therefore, add | 
 | 1507 |   // it to the list of nested classes within its parent. | 
 | 1508 |   assert(CurScope->isClassScope() && "Nested class outside of class scope?"); | 
 | 1509 |   ClassStack.top()->NestedClasses.push_back(Victim); | 
 | 1510 |   Victim->TemplateScope = CurScope->getParent()->isTemplateParamScope(); | 
 | 1511 | } |