aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2024-10-04 12:01:38 +1000
committerNathaniel Shead <nathanieloshead@gmail.com>2024-10-04 20:30:04 +1000
commit247643c7e21b087e6c93b8b8d49b4268bf84b03b (patch)
treea87f2eb8832ba8b9d7aecfe9e1bf7bea0f679ad0 /gcc
parent6a1e109158940ce3a2d1ceed3e1b614ea6c9a2de (diff)
downloadgcc-247643c7e21b087e6c93b8b8d49b4268bf84b03b.zip
gcc-247643c7e21b087e6c93b8b8d49b4268bf84b03b.tar.gz
gcc-247643c7e21b087e6c93b8b8d49b4268bf84b03b.tar.bz2
c++: Allow references to internal-linkage vars in C++11 [PR113266]
[temp.arg.nontype] changed in C++11 to allow naming internal-linkage variables and functions. We currently already handle internal-linkage functions, but variables were missed; this patch updates this. PR c++/113266 PR c++/116911 gcc/cp/ChangeLog: * parser.cc (cp_parser_template_argument): Allow internal-linkage variables since C++11. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/nontype6.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/parser.cc17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nontype6.C19
2 files changed, 31 insertions, 5 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 08f9c89..9d31a97 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -19864,9 +19864,11 @@ cp_parser_template_argument (cp_parser* parser)
-- the name of a non-type template-parameter; or
- -- the name of an object or function with external linkage...
+ -- the name of an object or function with external (or internal,
+ since C++11) linkage...
- -- the address of an object or function with external linkage...
+ -- the address of an object or function with external (or internal,
+ since C++11) linkage...
-- a pointer to member... */
/* Look for a non-type template parameter. */
@@ -19929,11 +19931,16 @@ cp_parser_template_argument (cp_parser* parser)
probe = TREE_OPERAND (probe, 1);
if (VAR_P (probe))
{
- /* A variable without external linkage might still be a
+ /* A variable without valid linkage might still be a
valid constant-expression, so no error is issued here
if the external-linkage check fails. */
- if (!address_p && !DECL_EXTERNAL_LINKAGE_P (probe))
- cp_parser_simulate_error (parser);
+ if (!address_p)
+ {
+ linkage_kind linkage = decl_linkage (probe);
+ if (linkage != lk_external
+ && (cxx_dialect < cxx11 || linkage != lk_internal))
+ cp_parser_simulate_error (parser);
+ }
}
else if (is_overloaded_fn (argument))
/* All overloaded functions are allowed; if the external
diff --git a/gcc/testsuite/g++.dg/cpp0x/nontype6.C b/gcc/testsuite/g++.dg/cpp0x/nontype6.C
new file mode 100644
index 0000000..5543d1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nontype6.C
@@ -0,0 +1,19 @@
+// PR c++/113266, PR c++/116911
+// { dg-do compile }
+
+template <int &> struct a {};
+static int guard1;
+a<guard1> b; // { dg-error "constant-expression|invalid" "" { target c++98_only } }
+
+namespace {
+ int guard2;
+}
+a<guard2> c; // OK in C++98 because guard2 has external linkage
+ // OK since C++11 because we can refer to an internal linkage decl
+
+void nolinkage() {
+ static int guard3;
+ a<guard3> d; // { dg-error "constant-expression|invalid" "" { target c++98_only } }
+ // { dg-error "constant expression|no linkage" "" { target { c++11 && c++14_down } } .-1 }
+ // OK since C++17 since we can now refer to no-linkage decls
+}