Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2018-01-22 05:56:56 +0000
committerNathan Ridge2018-02-04 21:10:40 +0000
commit1566253cb81542b7dd56cb8a5d5dfdae8b15ac4d (patch)
tree591d8e273e53439d6c5cf0fb6b3ce50373b48888
parent5c8a84960c0d2e5652a00da330546c7ab5f945b0 (diff)
downloadorg.eclipse.cdt-1566253cb81542b7dd56cb8a5d5dfdae8b15ac4d.tar.gz
org.eclipse.cdt-1566253cb81542b7dd56cb8a5d5dfdae8b15ac4d.tar.xz
org.eclipse.cdt-1566253cb81542b7dd56cb8a5d5dfdae8b15ac4d.zip
Bug 490359 - Add support for C++17 nested namespace definitions
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java15
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java49
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 0ab6bd5d649..ee434fc2da8 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
@@ -12599,4 +12599,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 083e07dd0ab..b5c724f3730 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
@@ -2646,9 +2646,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();
@@ -2658,16 +2658,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;
}

Back to the top