diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-11-08 05:37:34 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-11-08 05:37:34 +0000 |
commit | 13307f5f24299d35a0bf944153bc3d673fccadf6 (patch) | |
tree | 934e824c1c7d4d979ca98fe421de8c35193d7789 /clang/lib/Parse/ParseDeclCXX.cpp | |
parent | 0f0af19b058151690ec02d781d0039fb1fc38426 (diff) | |
download | bcm5719-llvm-13307f5f24299d35a0bf944153bc3d673fccadf6.tar.gz bcm5719-llvm-13307f5f24299d35a0bf944153bc3d673fccadf6.zip |
[c++1z] Implement nested-namespace-definitions.
This allows 'namespace A::B { ... }' as a shorthand for 'namespace A {
namespace B { ... } }'. We already supported this correctly for error recovery;
promote that support to a full implementation.
This is not the right implementation: we do not maintain source fidelity
because we desugar the nested namespace definition in the parser. This is
tricky to avoid, since the definition genuinely does inject one named
entity per level in the namespace name.
llvm-svn: 221574
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index e5cf84a74f9..223046c90d9 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -110,39 +110,36 @@ Decl *Parser::ParseNamespace(unsigned Context, BalancedDelimiterTracker T(*this, tok::l_brace); if (T.consumeOpen()) { - if (!ExtraIdent.empty()) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) - << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); - } - if (Ident) Diag(Tok, diag::err_expected) << tok::l_brace; else Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; - return nullptr; } if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() || getCurScope()->getFnParent()) { - if (!ExtraIdent.empty()) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) - << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); - } Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace); return nullptr; } - if (!ExtraIdent.empty()) { + if (ExtraIdent.empty()) { + // Normal namespace definition, not a nested-namespace-definition. + } else if (InlineLoc.isValid()) { + Diag(InlineLoc, diag::err_inline_nested_namespace_definition); + } else if (getLangOpts().CPlusPlus1z) { + Diag(ExtraNamespaceLoc[0], + diag::warn_cxx14_compat_nested_namespace_definition); + } else { TentativeParsingAction TPA(*this); SkipUntil(tok::r_brace, StopBeforeMatch); Token rBraceToken = Tok; TPA.Revert(); if (!rBraceToken.is(tok::r_brace)) { - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); } else { std::string NamespaceFix; @@ -156,7 +153,7 @@ Decl *Parser::ParseNamespace(unsigned Context, for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i) RBraces += "} "; - Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition) << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()), NamespaceFix) @@ -195,11 +192,11 @@ Decl *Parser::ParseNamespace(unsigned Context, } /// ParseInnerNamespace - Parse the contents of a namespace. -void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, - std::vector<IdentifierInfo*>& Ident, - std::vector<SourceLocation>& NamespaceLoc, - unsigned int index, SourceLocation& InlineLoc, - ParsedAttributes& attrs, +void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, + std::vector<IdentifierInfo *> &Ident, + std::vector<SourceLocation> &NamespaceLoc, + unsigned int index, SourceLocation &InlineLoc, + ParsedAttributes &attrs, BalancedDelimiterTracker &Tracker) { if (index == Ident.size()) { while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { @@ -216,7 +213,9 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, return; } - // Parse improperly nested namespaces. + // Handle a nested namespace definition. + // FIXME: Preserve the source information through to the AST rather than + // desugaring it here. ParseScope NamespaceScope(this, Scope::DeclScope); Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), |