ParseDeclCXX.cpp revision ff871444421ad9fb8e7ddb73bc422912d9b0ee53
1//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file implements the C++ Declaration portions of the Parser interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
15#include "clang/Basic/Diagnostic.h"
16#include "clang/Parse/DeclSpec.h"
17#include "clang/Parse/Scope.h"
18using namespace clang;
19
20/// ParseNamespace - We know that the current token is a namespace keyword. This
21/// may either be a top level namespace or a block-level namespace alias.
22///
23///       namespace-definition: [C++ 7.3: basic.namespace]
24///         named-namespace-definition
25///         unnamed-namespace-definition
26///
27///       unnamed-namespace-definition:
28///         'namespace' attributes[opt] '{' namespace-body '}'
29///
30///       named-namespace-definition:
31///         original-namespace-definition
32///         extension-namespace-definition
33///
34///       original-namespace-definition:
35///         'namespace' identifier attributes[opt] '{' namespace-body '}'
36///
37///       extension-namespace-definition:
38///         'namespace' original-namespace-name '{' namespace-body '}'
39///
40///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias]
41///         'namespace' identifier '=' qualified-namespace-specifier ';'
42///
43Parser::DeclTy *Parser::ParseNamespace(unsigned Context) {
44  assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
45  SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'.
46
47  SourceLocation IdentLoc;
48  IdentifierInfo *Ident = 0;
49
50  if (Tok.is(tok::identifier)) {
51    Ident = Tok.getIdentifierInfo();
52    IdentLoc = ConsumeToken();  // eat the identifier.
53  }
54
55  // Read label attributes, if present.
56  DeclTy *AttrList = 0;
57  if (Tok.is(tok::kw___attribute))
58    // FIXME: save these somewhere.
59    AttrList = ParseAttributes();
60
61  if (Tok.is(tok::equal)) {
62    // FIXME: Verify no attributes were present.
63    // FIXME: parse this.
64  } else if (Tok.is(tok::l_brace)) {
65
66    SourceLocation LBrace = ConsumeBrace();
67
68    // Enter a scope for the namespace.
69    EnterScope(Scope::DeclScope);
70
71    DeclTy *NamespcDecl =
72      Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace);
73
74    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
75      ParseExternalDeclaration();
76
77    // Leave the namespace scope.
78    ExitScope();
79
80    SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
81    Actions.ActOnFinishNamespaceDef(NamespcDecl, RBrace);
82
83    return NamespcDecl;
84
85  } else {
86    unsigned D = Ident ? diag::err_expected_lbrace :
87                         diag::err_expected_ident_lbrace;
88    Diag(Tok.getLocation(), D);
89  }
90
91  return 0;
92}
93
94/// ParseLinkage - We know that the current token is a string_literal
95/// and just before that, that extern was seen.
96///
97///       linkage-specification: [C++ 7.5p2: dcl.link]
98///         'extern' string-literal '{' declaration-seq[opt] '}'
99///         'extern' string-literal declaration
100///
101Parser::DeclTy *Parser::ParseLinkage(unsigned Context) {
102  assert(Tok.is(tok::string_literal) && "Not a stringliteral!");
103  llvm::SmallVector<char, 8> LangBuffer;
104  // LangBuffer is guaranteed to be big enough.
105  LangBuffer.resize(Tok.getLength());
106  const char *LangBufPtr = &LangBuffer[0];
107  unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
108
109  SourceLocation Loc = ConsumeStringToken();
110  DeclTy *D = 0;
111  SourceLocation LBrace, RBrace;
112
113  if (Tok.isNot(tok::l_brace)) {
114    D = ParseDeclaration(Context);
115  } else {
116    LBrace = ConsumeBrace();
117    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
118      // FIXME capture the decls.
119      D = ParseExternalDeclaration();
120    }
121
122    RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
123  }
124
125  if (!D)
126    return 0;
127
128  return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D);
129}
130
131/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
132/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
133/// until we reach the start of a definition or see a token that
134/// cannot start a definition.
135///
136///       class-specifier: [C++ class]
137///         class-head '{' member-specification[opt] '}'
138///         class-head '{' member-specification[opt] '}' attributes[opt]
139///       class-head:
140///         class-key identifier[opt] base-clause[opt]
141///         class-key nested-name-specifier identifier base-clause[opt]
142///         class-key nested-name-specifier[opt] simple-template-id
143///                          base-clause[opt]
144/// [GNU]   class-key attributes[opt] identifier[opt] base-clause[opt]
145/// [GNU]   class-key attributes[opt] nested-name-specifier
146///                          identifier base-clause[opt]
147/// [GNU]   class-key attributes[opt] nested-name-specifier[opt]
148///                          simple-template-id base-clause[opt]
149///       class-key:
150///         'class'
151///         'struct'
152///         'union'
153///
154///       elaborated-type-specifier: [C++ dcl.type.elab]
155///         class-key ::[opt] nested-name-specifier[opt] identifier
156///         class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
157///                          simple-template-id
158///
159///  Note that the C++ class-specifier and elaborated-type-specifier,
160///  together, subsume the C99 struct-or-union-specifier:
161///
162///       struct-or-union-specifier: [C99 6.7.2.1]
163///         struct-or-union identifier[opt] '{' struct-contents '}'
164///         struct-or-union identifier
165/// [GNU]   struct-or-union attributes[opt] identifier[opt] '{' struct-contents
166///                                                         '}' attributes[opt]
167/// [GNU]   struct-or-union attributes[opt] identifier
168///       struct-or-union:
169///         'struct'
170///         'union'
171void Parser::ParseClassSpecifier(DeclSpec &DS) {
172  assert((Tok.is(tok::kw_class) ||
173          Tok.is(tok::kw_struct) ||
174          Tok.is(tok::kw_union)) &&
175         "Not a class specifier");
176  DeclSpec::TST TagType =
177    Tok.is(tok::kw_class) ? DeclSpec::TST_class :
178    Tok.is(tok::kw_struct) ? DeclSpec::TST_struct :
179    DeclSpec::TST_union;
180
181  SourceLocation StartLoc = ConsumeToken();
182
183  AttributeList *Attr = 0;
184  // If attributes exist after tag, parse them.
185  if (Tok.is(tok::kw___attribute))
186    Attr = ParseAttributes();
187
188  // FIXME: Parse the (optional) nested-name-specifier.
189
190  // Parse the (optional) class name.
191  // FIXME: Alternatively, parse a simple-template-id.
192  IdentifierInfo *Name = 0;
193  SourceLocation NameLoc;
194  if (Tok.is(tok::identifier)) {
195    Name = Tok.getIdentifierInfo();
196    NameLoc = ConsumeToken();
197  }
198
199  // There are three options here.  If we have 'struct foo;', then
200  // this is a forward declaration.  If we have 'struct foo {...' or
201  // 'struct fo :...' then this is a definition. Otherwise we have
202  // something like 'struct foo xyz', a reference.
203  Action::TagKind TK;
204  if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)))
205    TK = Action::TK_Definition;
206  else if (Tok.is(tok::semi))
207    TK = Action::TK_Declaration;
208  else
209    TK = Action::TK_Reference;
210
211  if (!Name && TK != Action::TK_Definition) {
212    // We have a declaration or reference to an anonymous class.
213    Diag(StartLoc, diag::err_anon_type_definition,
214         DeclSpec::getSpecifierName(TagType));
215
216    // Skip the rest of this declarator, up until the comma or semicolon.
217    SkipUntil(tok::comma, true);
218    return;
219  }
220
221  // Parse the tag portion of this.
222  DeclTy *TagDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, Name,
223                                     NameLoc, Attr);
224
225  // Parse the optional base clause (C++ only).
226  if (getLang().CPlusPlus && Tok.is(tok::colon)) {
227    ParseBaseClause(TagDecl);
228  }
229
230  // If there is a body, parse it and inform the actions module.
231  if (Tok.is(tok::l_brace))
232    ParseStructUnionBody(StartLoc, TagType, TagDecl);
233  else if (TK == Action::TK_Definition) {
234    // FIXME: Complain that we have a base-specifier list but no
235    // definition.
236    Diag(Tok.getLocation(), diag::err_expected_lbrace);
237  }
238
239  const char *PrevSpec = 0;
240  if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl))
241    Diag(StartLoc, diag::err_invalid_decl_spec_combination, PrevSpec);
242}
243
244/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
245///
246///       base-clause : [C++ class.derived]
247///         ':' base-specifier-list
248///       base-specifier-list:
249///         base-specifier '...'[opt]
250///         base-specifier-list ',' base-specifier '...'[opt]
251void Parser::ParseBaseClause(DeclTy *ClassDecl)
252{
253  assert(Tok.is(tok::colon) && "Not a base clause");
254  ConsumeToken();
255
256  while (true) {
257    // Parse a base-specifier.
258    if (ParseBaseSpecifier(ClassDecl)) {
259      // Skip the rest of this base specifier, up until the comma or
260      // opening brace.
261      SkipUntil(tok::comma, tok::l_brace);
262    }
263
264    // If the next token is a comma, consume it and keep reading
265    // base-specifiers.
266    if (Tok.isNot(tok::comma)) break;
267
268    // Consume the comma.
269    ConsumeToken();
270  }
271}
272
273/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
274/// one entry in the base class list of a class specifier, for example:
275///    class foo : public bar, virtual private baz {
276/// 'public bar' and 'virtual private baz' are each base-specifiers.
277///
278///       base-specifier: [C++ class.derived]
279///         ::[opt] nested-name-specifier[opt] class-name
280///         'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
281///                        class-name
282///         access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
283///                        class-name
284bool Parser::ParseBaseSpecifier(DeclTy *ClassDecl)
285{
286  bool IsVirtual = false;
287  SourceLocation StartLoc = Tok.getLocation();
288
289  // Parse the 'virtual' keyword.
290  if (Tok.is(tok::kw_virtual))  {
291    ConsumeToken();
292    IsVirtual = true;
293  }
294
295  // Parse an (optional) access specifier.
296  AccessSpecifier Access = getAccessSpecifierIfPresent();
297  if (Access)
298    ConsumeToken();
299
300  // Parse the 'virtual' keyword (again!), in case it came after the
301  // access specifier.
302  if (Tok.is(tok::kw_virtual))  {
303    SourceLocation VirtualLoc = ConsumeToken();
304    if (IsVirtual) {
305      // Complain about duplicate 'virtual'
306      Diag(VirtualLoc, diag::err_dup_virtual);
307    }
308
309    IsVirtual = true;
310  }
311
312  // FIXME: Parse optional '::' and optional nested-name-specifier.
313
314  // Parse the class-name.
315  // FIXME: Alternatively, parse a simple-template-id.
316  if (Tok.isNot(tok::identifier)) {
317    Diag(Tok.getLocation(), diag::err_expected_class_name);
318    return true;
319  }
320
321  // We have an identifier; check whether it is actually a type.
322  DeclTy *BaseType = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope);
323  if (!BaseType) {
324    Diag(Tok.getLocation(), diag::err_expected_class_name);
325    return true;
326  }
327
328  // The location of the base class itself.
329  SourceLocation BaseLoc = Tok.getLocation();
330
331  // Find the complete source range for the base-specifier.
332  SourceRange Range(StartLoc, BaseLoc);
333
334  // Consume the identifier token (finally!).
335  ConsumeToken();
336
337  // Notify semantic analysis that we have parsed a complete
338  // base-specifier.
339  Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, BaseType,
340                             BaseLoc);
341  return false;
342}
343
344/// getAccessSpecifierIfPresent - Determine whether the next token is
345/// a C++ access-specifier.
346///
347///       access-specifier: [C++ class.derived]
348///         'private'
349///         'protected'
350///         'public'
351AccessSpecifier Parser::getAccessSpecifierIfPresent() const
352{
353  switch (Tok.getKind()) {
354  default: return AS_none;
355  case tok::kw_private: return AS_private;
356  case tok::kw_protected: return AS_protected;
357  case tok::kw_public: return AS_public;
358  }
359}
360