Chris Lattner | f7b2e55 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 1 | //===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
Chris Lattner | 959e5be | 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 | f7b2e55 | 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 | |
| 14 | #include "clang/Parse/Parser.h" |
| 15 | #include "clang/Parse/Scope.h" |
| 16 | #include "clang/Basic/Diagnostic.h" |
| 17 | using namespace clang; |
| 18 | |
| 19 | /// ParseNamespace - We know that the current token is a namespace keyword. This |
| 20 | /// may either be a top level namespace or a block-level namespace alias. |
| 21 | /// |
| 22 | /// namespace-definition: [C++ 7.3: basic.namespace] |
| 23 | /// named-namespace-definition |
| 24 | /// unnamed-namespace-definition |
| 25 | /// |
| 26 | /// unnamed-namespace-definition: |
| 27 | /// 'namespace' attributes[opt] '{' namespace-body '}' |
| 28 | /// |
| 29 | /// named-namespace-definition: |
| 30 | /// original-namespace-definition |
| 31 | /// extension-namespace-definition |
| 32 | /// |
| 33 | /// original-namespace-definition: |
| 34 | /// 'namespace' identifier attributes[opt] '{' namespace-body '}' |
| 35 | /// |
| 36 | /// extension-namespace-definition: |
| 37 | /// 'namespace' original-namespace-name '{' namespace-body '}' |
| 38 | /// |
| 39 | /// namespace-alias-definition: [C++ 7.3.2: namespace.alias] |
| 40 | /// 'namespace' identifier '=' qualified-namespace-specifier ';' |
| 41 | /// |
| 42 | Parser::DeclTy *Parser::ParseNamespace(unsigned Context) { |
Chris Lattner | 34a01ad | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 43 | assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); |
Chris Lattner | f7b2e55 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 44 | SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. |
| 45 | |
| 46 | SourceLocation IdentLoc; |
| 47 | IdentifierInfo *Ident = 0; |
| 48 | |
Chris Lattner | 34a01ad | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 49 | if (Tok.is(tok::identifier)) { |
Chris Lattner | f7b2e55 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 50 | Ident = Tok.getIdentifierInfo(); |
| 51 | IdentLoc = ConsumeToken(); // eat the identifier. |
| 52 | } |
| 53 | |
| 54 | // Read label attributes, if present. |
| 55 | DeclTy *AttrList = 0; |
Chris Lattner | 34a01ad | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 56 | if (Tok.is(tok::kw___attribute)) |
Chris Lattner | f7b2e55 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 57 | // FIXME: save these somewhere. |
| 58 | AttrList = ParseAttributes(); |
| 59 | |
Chris Lattner | 34a01ad | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 60 | if (Tok.is(tok::equal)) { |
Chris Lattner | f7b2e55 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 61 | // FIXME: Verify no attributes were present. |
| 62 | // FIXME: parse this. |
Chris Lattner | 34a01ad | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 63 | } else if (Tok.is(tok::l_brace)) { |
Chris Lattner | f7b2e55 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 64 | SourceLocation LBrace = ConsumeBrace(); |
| 65 | // FIXME: push a scope, push a namespace decl. |
| 66 | |
Chris Lattner | 34a01ad | 2007-10-09 17:33:22 +0000 | [diff] [blame] | 67 | while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { |
Chris Lattner | 9c13572 | 2007-08-25 18:15:16 +0000 | [diff] [blame] | 68 | // FIXME capture the decls. |
| 69 | ParseExternalDeclaration(); |
| 70 | } |
Chris Lattner | f7b2e55 | 2007-08-25 06:57:03 +0000 | [diff] [blame] | 71 | |
| 72 | SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); |
| 73 | |
| 74 | // FIXME: act on this. |
| 75 | } else { |
| 76 | unsigned D = Ident ? diag::err_expected_lbrace : |
| 77 | diag::err_expected_ident_lbrace; |
| 78 | Diag(Tok.getLocation(), D); |
| 79 | } |
| 80 | |
| 81 | return 0; |
| 82 | } |
Chris Lattner | 806a5f5 | 2008-01-12 07:05:38 +0000 | [diff] [blame^] | 83 | |
| 84 | /// ParseLinkage - We know that the current token is a string_literal |
| 85 | /// and just before that, that extern was seen. |
| 86 | /// |
| 87 | /// linkage-specification: [C++ 7.5p2: dcl.link] |
| 88 | /// 'extern' string-literal '{' declaration-seq[opt] '}' |
| 89 | /// 'extern' string-literal declaration |
| 90 | /// |
| 91 | Parser::DeclTy *Parser::ParseLinkage(unsigned Context) { |
| 92 | assert(Tok.is(tok::string_literal) && "Not a stringliteral!"); |
| 93 | llvm::SmallVector<char, 8> LangBuffer; |
| 94 | // LangBuffer is guaranteed to be big enough. |
| 95 | LangBuffer.resize(Tok.getLength()); |
| 96 | const char *LangBufPtr = &LangBuffer[0]; |
| 97 | unsigned StrSize = PP.getSpelling(Tok, LangBufPtr); |
| 98 | |
| 99 | SourceLocation Loc = ConsumeStringToken(); |
| 100 | DeclTy *D = 0; |
| 101 | SourceLocation LBrace, RBrace; |
| 102 | |
| 103 | if (Tok.isNot(tok::l_brace)) { |
| 104 | D = ParseDeclaration(Context); |
| 105 | } else { |
| 106 | LBrace = ConsumeBrace(); |
| 107 | while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { |
| 108 | // FIXME capture the decls. |
| 109 | D = ParseExternalDeclaration(); |
| 110 | } |
| 111 | |
| 112 | RBrace = MatchRHSPunctuation(tok::r_brace, LBrace); |
| 113 | } |
| 114 | |
| 115 | if (!D) |
| 116 | return 0; |
| 117 | |
| 118 | return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D); |
| 119 | } |