diff options
author | Nathan Ridge | 2018-01-22 05:56:56 +0000 |
---|---|---|
committer | Nathan Ridge | 2018-01-25 22:32:58 +0000 |
commit | f413c21d032e4428bda60528983493cbf45845b5 (patch) | |
tree | 11590ffc0f7b8397a6b4cd3a15cc1a606de2d5db /core | |
parent | 69c84d4f054f8291fcd674a4f8a19ccc61505f04 (diff) | |
download | org.eclipse.cdt-f413c21d032e4428bda60528983493cbf45845b5.tar.gz org.eclipse.cdt-f413c21d032e4428bda60528983493cbf45845b5.tar.xz org.eclipse.cdt-f413c21d032e4428bda60528983493cbf45845b5.zip |
Bug 490359 - Add support for C++17 nested namespace definitions
Change-Id: I5f2550e607195335475427f6fced63bf97eaa718
Diffstat (limited to 'core')
2 files changed, 59 insertions, 5 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 9f78539d759..e7c1c2b670f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -12632,4 +12632,19 @@ public class AST2CPPTests extends AST2CPPTestBase { helper.assertVariableValue("waldo4", 0); helper.assertVariableValue("waldo5", 0); } + + // namespace x { + // void foo(); + // } + // namespace x::y { + // void bar() { + // foo(); + // } + // } + // int main() { + // x::y::bar(); + // } + public void testNestedNamespaceDefinition_490359() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index f35d19f3b5c..abc34b9f5da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -2638,9 +2638,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { consume(IToken.t_namespace); // optional name - IASTName name = null; + ICPPASTName name = null; if (LT(1) == IToken.tIDENTIFIER) { - name = identifier(); + name = qualifiedName(); endOffset= calculateEndOffset(name); } else { name = getNodeFactory().newName(); @@ -2650,16 +2650,55 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { List<IASTAttributeSpecifier> attributeSpecifiers = __attribute_decl_seq(true, false); if (LT(1) == IToken.tLBRACE) { - ICPPASTNamespaceDefinition ns = getNodeFactory().newNamespaceDefinition(name); + ICPPASTNamespaceDefinition outer = null; + ICPPASTNamespaceDefinition inner = null; + if (name instanceof ICPPASTQualifiedName) { + // Handle C++17 nested namespace definition. + ICPPASTNameSpecifier[] qualifier = ((ICPPASTQualifiedName) name).getQualifier(); + for (ICPPASTNameSpecifier specifier : qualifier) { + if (!(specifier instanceof ICPPASTName)) { + // No decltype-specifiers in nested namespace definition. + throwBacktrack(specifier); + return null; + } + ICPPASTName segment = (ICPPASTName) specifier; + ICPPASTNamespaceDefinition ns = getNodeFactory().newNamespaceDefinition(segment); + if (outer == null || inner == null) { // second half of condition is just to avoid warning + outer = ns; + } else { + inner.addDeclaration(ns); + } + inner = ns; + } + } + IASTName lastName = name.getLastName(); + ICPPASTNamespaceDefinition ns = getNodeFactory().newNamespaceDefinition(lastName); + if (outer == null || inner == null) { // second half of condition is just to avoid warning + outer = ns; + } else { + inner.addDeclaration(ns); + } ns.setIsInline(isInline); declarationListInBraces(ns, offset, DeclarationOptions.GLOBAL); + endOffset = getEndOffset(); + if (ns != outer) { + // For a C++17 nested namespace definition, we need to set the offset/length of + // the enclosing namespace declaration nodes (declarationListInBraces() does it + // for the inner one). + for (IASTNode parent = ns.getParent(); parent != null; parent = parent.getParent()) { + setRange(parent, offset, endOffset); + if (parent == outer) { + break; + } + } + } addAttributeSpecifiers(attributeSpecifiers, ns); - return ns; + return outer; } if (LT(1) == IToken.tASSIGN) { endOffset= consume().getEndOffset(); - if (name.toString() == null) { + if (name.toString() == null || name instanceof ICPPASTQualifiedName) { throwBacktrack(offset, endOffset - offset); return null; } |