From patchwork Sun Nov 2 14:15:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Trippelsdorf X-Patchwork-Id: 405891 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A181A140081 for ; Mon, 3 Nov 2014 01:16:03 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=HgvVUc+AUmnHZbBvp SxzBY451Oycj0YMgmiQTBFDnYDpheN1mabW+npHFxDe9nLfr3vjbmQTuJDk5qSEU DK4Ih1rF2wMLGcyIWerMxQ8m6km34uvFfw2Wqz1ldxcDmXrGzKw5vPpCNeiB1BZy UzrOW1lpiDjXij5Mk1sa73w6qQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=default; bh=2rwiZkOyYAzlqmf0lKKHNh+ oz5w=; b=LaGp5UHVRZXEeP3S6PVl72oBHCFpQdfG7EkLYcuPZbzjDZJJCIc4z4t 0inLPIi8bi8pcrsCgUBAIo4GZAQHCrjqWVyB+i/WmxkM0eH3a5gqqgBEQ6keD/p/ m4ldPfSYYcii+lbGeuRfwZ16f1WmPVno7IXD0mgDjDs0Ctn+OsYY= Received: (qmail 19415 invoked by alias); 2 Nov 2014 14:15:56 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 19403 invoked by uid 89); 2 Nov 2014 14:15:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.0 required=5.0 tests=AWL, BAYES_50, KAM_MXURI, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=no version=3.3.2 X-HELO: mail.ud10.udmedia.de Received: from ud10.udmedia.de (HELO mail.ud10.udmedia.de) (194.117.254.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 02 Nov 2014 14:15:54 +0000 Received: (qmail 14359 invoked from network); 2 Nov 2014 15:15:50 +0100 Received: from unknown (HELO x4) (ud10?360p3@91.64.94.144) by mail.ud10.udmedia.de with ESMTPSA (DHE-RSA-AES256-SHA encrypted, authenticated); 2 Nov 2014 15:15:50 +0100 Date: Sun, 2 Nov 2014 15:15:50 +0100 From: Markus Trippelsdorf To: gcc-patches@gcc.gnu.org Cc: Jason Merrill Subject: [PATCH v2] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace. Message-ID: <20141102141550.GD31234@x4> References: <20141102125814.GB31234@x4> <20141102132914.GC31234@x4> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20141102132914.GC31234@x4> (Fixed g++.dg/template/spec25.C issue. Sorry for the churn.) DR374: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374 allows explicit specialization of templates in the enclosing namespace. Because this idiom is currently already accepted with -fpermissive, the fix is easy: Just skip the calls to permerror(). Tested on powerpc64-unknown-linux-gnu. OK for trunk? Thanks again. 2014-11-02 Markus Trippelsdorf DR 374 PR c++/56480 * pt.c (check_explicit_instantiation_namespace): Move above. * pt.c (check_specialization_namespace): Skip permerror() for C++11 and up. Make sure instantiation is valid in current namespace. DR 374 PR c++/56480 * g++.dg/template/spec17.C: Don't dg-error for C++11 and up. * g++.dg/template/spec25.C: Likewise. Adjust regex. * g++.dg/template/spec36.C: Don't dg-error for C++11 and up. * g++.old-deja/g++.ns/template13.C: Likewise. * g++.old-deja/g++.pt/explicit73.C: Likewise. * g++.old-deja/g++.pt/lookup10.C: Likewise. --- gcc/cp/pt.c | 45 +++++++++++++++----------- gcc/testsuite/g++.dg/template/spec17.C | 4 +-- gcc/testsuite/g++.dg/template/spec25.C | 4 +-- gcc/testsuite/g++.dg/template/spec36.C | 4 +-- gcc/testsuite/g++.old-deja/g++.ns/template13.C | 6 ++-- gcc/testsuite/g++.old-deja/g++.pt/explicit73.C | 4 +-- gcc/testsuite/g++.old-deja/g++.pt/lookup10.C | 4 +-- 7 files changed, 39 insertions(+), 32 deletions(-) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2cf10f442f68..8672202f91e2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -755,6 +755,23 @@ end_explicit_instantiation (void) processing_explicit_instantiation = false; } +/* SPEC is an explicit instantiation. Check that it is valid to + perform this explicit instantiation in the current namespace. */ + +static void +check_explicit_instantiation_namespace (tree spec) +{ + tree ns; + + /* DR 275: An explicit instantiation shall appear in an enclosing + namespace of its template. */ + ns = decl_namespace_context (spec); + if (!is_ancestor (current_namespace, ns)) + permerror (input_location, "explicit instantiation of %qD in namespace %qD " + "(which does not enclose namespace %qD)", + spec, current_namespace, ns); +} + /* An explicit specialization or partial specialization of TMPL is being declared. Check that the namespace in which the specialization is occurring is permissible. Returns false iff it is invalid to @@ -785,29 +802,19 @@ check_specialization_namespace (tree tmpl) return true; else { - permerror (input_location, "specialization of %qD in different namespace", tmpl); - permerror (input_location, " from definition of %q+#D", tmpl); + if (cxx_dialect < cxx11) + { + permerror (input_location, "specialization of %qD in different " + "namespace", tmpl); + permerror (input_location, " from definition of %q+#D", tmpl); + } + else + check_explicit_instantiation_namespace (tmpl); + return false; } } -/* SPEC is an explicit instantiation. Check that it is valid to - perform this explicit instantiation in the current namespace. */ - -static void -check_explicit_instantiation_namespace (tree spec) -{ - tree ns; - - /* DR 275: An explicit instantiation shall appear in an enclosing - namespace of its template. */ - ns = decl_namespace_context (spec); - if (!is_ancestor (current_namespace, ns)) - permerror (input_location, "explicit instantiation of %qD in namespace %qD " - "(which does not enclose namespace %qD)", - spec, current_namespace, ns); -} - /* The TYPE is being declared. If it is a template type, that means it is a partial specialization. Do appropriate error-checking. */ diff --git a/gcc/testsuite/g++.dg/template/spec17.C b/gcc/testsuite/g++.dg/template/spec17.C index 237557684238..70e5be28e05a 100644 --- a/gcc/testsuite/g++.dg/template/spec17.C +++ b/gcc/testsuite/g++.dg/template/spec17.C @@ -1,11 +1,11 @@ // PR c++/16224 namespace io { - template int foo(); // { dg-error "" } + template int foo(); // { dg-error "" "" { target { ! c++11 } } } } using namespace io; -template<> int foo(); // { dg-error "" } +template<> int foo(); // { dg-error "" "" { target { ! c++11 } } } int a = foo(); diff --git a/gcc/testsuite/g++.dg/template/spec25.C b/gcc/testsuite/g++.dg/template/spec25.C index 385d19ada0c4..c3836261f6af 100644 --- a/gcc/testsuite/g++.dg/template/spec25.C +++ b/gcc/testsuite/g++.dg/template/spec25.C @@ -1,10 +1,10 @@ namespace N { template struct S { - void f() {} // { dg-error "definition" } + void f() {} // { dg-error "definition" "" { target { ! c++11 } } } }; } namespace K { - template <> void N::S::f() {} // { dg-error "different namespace" } + template <> void N::S::f() {} // { dg-error "namespace" } } diff --git a/gcc/testsuite/g++.dg/template/spec36.C b/gcc/testsuite/g++.dg/template/spec36.C index 7e8dc5241d9f..d9c57824b7e5 100644 --- a/gcc/testsuite/g++.dg/template/spec36.C +++ b/gcc/testsuite/g++.dg/template/spec36.C @@ -8,9 +8,9 @@ struct basic_string namespace MyNS { class MyClass { template - T test() { } /* { dg-error "from definition" } */ + T test() { } /* { dg-error "from definition" "" { target { ! c++11 } } } */ }; } template <> -basic_string MyNS::MyClass::test() /* { dg-error "specialization of" } */ +basic_string MyNS::MyClass::test() /* { dg-error "specialization of" "" { target { ! c++11 } } } */ { return 1; } diff --git a/gcc/testsuite/g++.old-deja/g++.ns/template13.C b/gcc/testsuite/g++.old-deja/g++.ns/template13.C index a9559c7153b6..21ad61847b73 100644 --- a/gcc/testsuite/g++.old-deja/g++.ns/template13.C +++ b/gcc/testsuite/g++.old-deja/g++.ns/template13.C @@ -4,18 +4,18 @@ namespace bar { // trick it to provide some prior declaration template - void foo(); // { dg-error "definition" } + void foo(); // { dg-error "definition" "" { target { ! c++11 } } } templateclass X; // { dg-message "note: previous declaration" } } template T const -bar::foo(T const &a) // { dg-error "" "" { xfail *-*-* } } not declared in bar - +bar::foo(T const &a) // { dg-error "" "" { xfail *-*-* } } not declared in bar - { return a; } -template<> void bar::foo() // { dg-error "different namespace" } +template<> void bar::foo() // { dg-error "different namespace" "" { target { ! c++11 } } } { } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C index 1d83e3468289..bcf4fe7f21a5 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C @@ -7,9 +7,9 @@ // the template namespace N { - template class foo; // { dg-error "" } referenced below + template class foo; // { dg-error "" "" { target { ! c++11 } } } referenced below } using namespace N; -template <> class foo; // { dg-error "" } invalid specialization +template <> class foo; // { dg-error "" "" { target { ! c++11 } } } invalid specialization diff --git a/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C b/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C index 1c04250fc3c0..0ed5dbe42c89 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C @@ -13,8 +13,8 @@ namespace Outer { namespace Core = Core_Real; namespace Core_Real { - template void Foo (T *) {} // { dg-error "definition" } + template void Foo (T *) {} // { dg-error "definition" "" { target { ! c++11 } } } } - template<> void Core::Foo<> (Render_Real::Type *) {} // { dg-error "" } + template<> void Core::Foo<> (Render_Real::Type *) {} // { dg-error "" "" { target { ! c++11 } } } }