From patchwork Mon Dec 1 03:21:36 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 4017 Received: (qmail 6962 invoked by alias); 1 Dec 2014 03:22:02 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 6926 invoked by uid 89); 1 Dec 2014 03:21:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-qc0-f180.google.com Received: from mail-qc0-f180.google.com (HELO mail-qc0-f180.google.com) (209.85.216.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 01 Dec 2014 03:21:55 +0000 Received: by mail-qc0-f180.google.com with SMTP id i8so6869971qcq.25 for ; Sun, 30 Nov 2014 19:21:53 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=8wYy1euJBxseNB9sf2l+YtdSm6Fn1olDieqvxoMkTtc=; b=UnKtP8tJ9iZVr7bRi0US/HQTvmbz0MgybJA1uex5Ld1IXdCioxKN07dSRZ4mgh6smE R/p5XX/g9rqXHqfVeW4HRk6F3S4Z1hxd0ZYn05Q2qy9n8+An4Xh1rznZR87/Qc4HUUxK 3hYtxHGkOw1zaHYd7qC8PRKIxKM7yJG/E4MC2IPFsrpHqFNEEsIDdzXwAOoZnRjx+o4P U65TicpsSPSrFaw7b0jVRHE8FoRH3JZ80DQQ/0v86ljdAsDY5mSlNNAWHst1nmyJO0pc yYgp4GeJLHS8ILote7pU90GctCfp7pLB0bo82/DQJoOlmNevoPmDmhDfV3yZBr0HvX9W E8hA== X-Gm-Message-State: ALoCoQmDV80wF0O4FRBQbLN+yPYmNaQMWKYtB1sP9VKP4rGKKhVqXjeEilXjvinVQS5nq7+T3QVH X-Received: by 10.224.36.14 with SMTP id r14mr24644706qad.39.1417404113275; Sun, 30 Nov 2014 19:21:53 -0800 (PST) Received: from localhost.localdomain (ool-4353af5c.dyn.optonline.net. [67.83.175.92]) by mx.google.com with ESMTPSA id y3sm16279165qae.2.2014.11.30.19.21.51 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 30 Nov 2014 19:21:51 -0800 (PST) From: Patrick Palka To: gdb-patches@sourceware.org Cc: Patrick Palka Subject: [PATCH] [RFC] PR c++/16874: make it easier to use anonymous namespaces Date: Sun, 30 Nov 2014 22:21:36 -0500 Message-Id: <1417404096-16170-1-git-send-email-patrick@parcs.ath.cx> X-IsSubscribed: yes Symbols referring to names defined inside a top-level C++ anonymous namespace have an "(anonymous namespace)::" prefix attached to them. Referring to such symbols in commands such as "print" and "break" is cumbersome because the prefix is tricky to type and symbols with this prefix do not TAB-complete properly. To make it easier to refer to such symbols, this patch allows the user to omit "(anonymous namespace)::" prefix from these symbols. In other words, this patch allows the symbol "(anonymous namespace)::FOO" to be referred to as "FOO". Likewise "(anonymous namespace)::FOO::BAR" ==> "FOO::BAR". But not "FOO::(anonymous namespace)::BAZ" ==> "FOO::BAZ" because the anonymous namespace in question is not the top-level one. It also doesn't handle "(anonymous namespace)::(anonymous namespace)::FOO" ==> "FOO". This patch is implemented in three hunks. The cp-namespace.c hunk handles the elision of the anon prefix during symbol lookup in the expression context (.e.g. "print foo"). The linespec.c hunk handles the elision of the anon prefix during symbol lookup in the breakpoint context (e.g. "break foo"). And finally the symtab.c hunk handles the elision of the anon prefix during symbol completion. This patch does not yet have a test case, but nonetheless I would very much appreciate comments on the approach that this patch takes in address the mentioned PR. I chose this approach because symbols defined in the root anonymous namespace are very akin to static symbols so it is intuitive and convenient to treat them as such, that is, to pretend that their (anonymous namespace):: prefix doesn't even exist (unless the prefix was explicitly given by the user). gdb/ChangeLog: * cp-support.h (cp_in_root_anonymous_namespace_p): New function. * cp-namespace.c (cp_lookup_symbol_nonlocal): Try looking for the symbol within the root anonymous namespace. * linespec.c (find_linespec_symbols): Likewise. * symtab.c (completion_list_add_name): Ignore the root anonymous namespace prefix when looking for matching symbols. --- gdb/cp-namespace.c | 23 +++++++++++++++++++++-- gdb/cp-support.h | 10 ++++++++++ gdb/linespec.c | 20 +++++++++++++++++++- gdb/symtab.c | 10 ++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index fcfd17b..149c3c1 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -233,8 +233,27 @@ cp_lookup_symbol_nonlocal (const char *name, if (sym != NULL) return sym; - return cp_lookup_symbol_namespace (scope, name, - block, domain); + sym = cp_lookup_symbol_namespace (scope, name, block, domain); + if (sym != NULL) + return sym; + + /* If we can't find the symbol then try searching for it inside the + root anonymous namespace, i.e. the symbol + (anonymous namespace)::NAME. */ + + if (!cp_in_root_anonymous_namespace_p (name)) + { + char *anon_name = alloca (strlen (CP_ANONYMOUS_NAMESPACE_STR "::") + + strlen (name) + 1); + strcpy (anon_name, CP_ANONYMOUS_NAMESPACE_STR "::"); + strcat (anon_name, name); + + sym = cp_lookup_symbol_nonlocal (anon_name, block, domain); + if (sym != NULL) + return sym; + } + + return NULL; } /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are diff --git a/gdb/cp-support.h b/gdb/cp-support.h index c0ae35b..10be09f 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -143,6 +143,16 @@ struct using_direct }; +/* Test whether SYMBOL correponds to a name inside the root anonymous + namespace. */ + +static inline int +cp_in_root_anonymous_namespace_p (const char *symbol) +{ + return strncmp (symbol, CP_ANONYMOUS_NAMESPACE_STR "::", + CP_ANONYMOUS_NAMESPACE_LEN + 2) == 0; +} + /* Functions from cp-support.c. */ extern char *cp_canonicalize_string (const char *string); diff --git a/gdb/linespec.c b/gdb/linespec.c index 82384ca..8a6c7f7 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -3134,7 +3134,25 @@ find_linespec_symbols (struct linespec_state *state, find_function_symbols (state, file_symtabs, lookup_name, symbols, minsyms); - /* If we were unable to locate a symbol of the same name, try dividing + /* For convenience, if LOOKUP_NAME was not found then look for + (anonymous namespace)::LOOKUP_NAME (C++ only). */ + + if (state->language->la_language == language_cplus + && VEC_empty (symbolp, *symbols) + && VEC_empty (bound_minimal_symbol_d, *minsyms) + && !cp_in_root_anonymous_namespace_p (name)) + { + char *new_lookup_name = alloca (strlen (CP_ANONYMOUS_NAMESPACE_STR "::") + + strlen (lookup_name) + 1); + + strcpy (new_lookup_name, CP_ANONYMOUS_NAMESPACE_STR "::"); + strcat (new_lookup_name, name); + + find_function_symbols (state, file_symtabs, new_lookup_name, + symbols, minsyms); + } + + /* If we were still unable to locate a corresponding symbol, try dividing the name into class and method names and searching the class and its baseclasses. */ if (VEC_empty (symbolp, *symbols) diff --git a/gdb/symtab.c b/gdb/symtab.c index 345c20d..30f0dbe 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -4164,6 +4164,16 @@ completion_list_add_name (const char *symname, const char *sym_text, int sym_text_len, const char *text, const char *word) { + /* Skip over the redundant "(anonymous namespace)::" prefix on symbols within + the root anonymous namespace so that if the user is completing the name + FOO then we want to match it with the symbol (anonymous namespace)::FOOBAR + and to output FOOBAR in the completion list (C++ only). */ + + if (current_language->la_language == language_cplus + && cp_in_root_anonymous_namespace_p (symname) + && !cp_in_root_anonymous_namespace_p (sym_text)) + symname += strlen (CP_ANONYMOUS_NAMESPACE_STR "::"); + /* Clip symbols that cannot match. */ if (!compare_symbol_name (symname, sym_text, sym_text_len)) return;