Restrict DR 757 change to C++0x mode.
authorJason Merrill <jason@redhat.com>
Mon, 2 Nov 2009 16:14:26 +0000 (11:14 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 2 Nov 2009 16:14:26 +0000 (11:14 -0500)
* decl2.c (mark_used): Check cxx_dialect.
* decl.c (grokfndecl): Do check type linkage in C++98 mode.
(grokvardecl): Likewise.
* pt.c (check_instantiated_arg): Likewise.

From-SVN: r153816

19 files changed:
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle32.C
gcc/testsuite/g++.dg/cpp0x/linkage2.C [moved from gcc/testsuite/g++.dg/other/linkage2.C with 97% similarity]
gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
gcc/testsuite/g++.dg/debug/dwarf2/anonname1.C
gcc/testsuite/g++.dg/ext/anon-struct4.C
gcc/testsuite/g++.dg/lookup/anon2.C
gcc/testsuite/g++.dg/other/anon3.C
gcc/testsuite/g++.dg/template/arg2.C
gcc/testsuite/g++.dg/template/local4.C
gcc/testsuite/g++.old-deja/g++.law/operators32.C
gcc/testsuite/g++.old-deja/g++.other/anon9.C
gcc/testsuite/g++.old-deja/g++.other/linkage1.C
gcc/testsuite/g++.old-deja/g++.other/linkage2.C
gcc/testsuite/g++.old-deja/g++.pt/enum6.C

index 044b568..1921f72 100644 (file)
@@ -1,3 +1,11 @@
+2009-11-02  Jason Merrill  <jason@redhat.com>
+
+       Restrict DR 757 change to C++0x mode.
+       * decl2.c (mark_used): Check cxx_dialect.
+       * decl.c (grokfndecl): Do check type linkage in C++98 mode.
+       (grokvardecl): Likewise.
+       * pt.c (check_instantiated_arg): Likewise.
+
 2009-11-02  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/41774
index 33023a7..de29d0b 100644 (file)
@@ -6768,6 +6768,36 @@ grokfndecl (tree ctype,
                || decl_function_context (TYPE_MAIN_DECL (ctype))))
     publicp = 0;
 
+  if (publicp && cxx_dialect == cxx98)
+    {
+      /* [basic.link]: A name with no linkage (notably, the name of a class
+        or enumeration declared in a local scope) shall not be used to
+        declare an entity with linkage.
+
+        DR 757 relaxes this restriction for C++0x.  */
+      t = no_linkage_check (TREE_TYPE (decl),
+                           /*relaxed_p=*/false);
+      if (t)
+       {
+         if (TYPE_ANONYMOUS_P (t))
+           {
+             if (DECL_EXTERN_C_P (decl))
+               /* Allow this; it's pretty common in C.  */;
+             else
+               {
+                 permerror (input_location, "non-local function %q#D uses anonymous type",
+                             decl);
+                 if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
+                   permerror (input_location, "%q+#D does not refer to the unqualified "
+                              "type, so it is not used for linkage",
+                              TYPE_NAME (t));
+               }
+           }
+         else
+           permerror (input_location, "non-local function %q#D uses local type %qT", decl, t);
+       }
+    }
+
   TREE_PUBLIC (decl) = publicp;
   if (! publicp)
     {
@@ -7007,15 +7037,48 @@ grokvardecl (tree type,
   if (declspecs->specs[(int)ds_thread])
     DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
 
+  /* If the type of the decl has no linkage, make sure that we'll
+     notice that in mark_used.  */
+  if (cxx_dialect > cxx98
+      && decl_linkage (decl) != lk_none
+      && DECL_LANG_SPECIFIC (decl) == NULL
+      && !DECL_EXTERN_C_P (decl)
+      && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
+    retrofit_lang_decl (decl);
+
   if (TREE_PUBLIC (decl))
     {
-      /* If the type of the decl has no linkage, make sure that we'll
-        notice that in mark_used.  */
-      if (DECL_LANG_SPECIFIC (decl) == NULL
-         && TREE_PUBLIC (decl)
-         && !DECL_EXTERN_C_P (decl)
-         && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
-       retrofit_lang_decl (decl);
+      /* [basic.link]: A name with no linkage (notably, the name of a class
+        or enumeration declared in a local scope) shall not be used to
+        declare an entity with linkage.
+
+        DR 757 relaxes this restriction for C++0x.  */
+      tree t = (cxx_dialect > cxx98 ? NULL_TREE
+               : no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false));
+      if (t)
+       {
+         if (TYPE_ANONYMOUS_P (t))
+           {
+             if (DECL_EXTERN_C_P (decl))
+               /* Allow this; it's pretty common in C.  */
+               ;
+             else
+               {
+                 /* DRs 132, 319 and 389 seem to indicate types with
+                    no linkage can only be used to declare extern "C"
+                    entities.  Since it's not always an error in the
+                    ISO C++ 90 Standard, we only issue a warning.  */
+                 warning (0, "non-local variable %q#D uses anonymous type",
+                          decl);
+                 if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
+                   warning (0, "%q+#D does not refer to the unqualified "
+                            "type, so it is not used for linkage",
+                            TYPE_NAME (t));
+               }
+           }
+         else
+           warning (0, "non-local variable %q#D uses local type %qT", decl, t);
+       }
     }
   else
     DECL_INTERFACE_KNOWN (decl) = 1;
index 592ee08..b1fe4b9 100644 (file)
@@ -3990,7 +3990,8 @@ mark_used (tree decl)
    o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
    o the variable or function is not used (3.2 [basic.def.odr]) or is
    defined in the same translation unit.  */
-  if (decl_linkage (decl) != lk_none
+  if (cxx_dialect > cxx98
+      && decl_linkage (decl) != lk_none
       && !DECL_EXTERN_C_P (decl)
       && !DECL_ARTIFICIAL (decl)
       && !decl_defined_p (decl)
index 9983a95..2f0fa12 100644 (file)
@@ -12479,7 +12479,7 @@ tsubst_copy_and_build (tree t,
 }
 
 /* Verify that the instantiated ARGS are valid. For type arguments,
-   make sure that the type is not variably modified. For non-type arguments,
+   make sure that the type's linkage is ok. For non-type arguments,
    make sure they are constants if they are integral or enumerations.
    Emit an error under control of COMPLAIN, and return TRUE on error.  */
 
@@ -12500,7 +12500,33 @@ check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
     }
   else if (TYPE_P (t))
     {
-      if (variably_modified_type_p (t, NULL_TREE))
+      /* [basic.link]: A name with no linkage (notably, the name
+        of a class or enumeration declared in a local scope)
+        shall not be used to declare an entity with linkage.
+        This implies that names with no linkage cannot be used as
+        template arguments
+
+        DR 757 relaxes this restriction for C++0x.  */
+      tree nt = (cxx_dialect > cxx98 ? NULL_TREE
+                : no_linkage_check (t, /*relaxed_p=*/false));
+
+      if (nt)
+       {
+         /* DR 488 makes use of a type with no linkage cause
+            type deduction to fail.  */
+         if (complain & tf_error)
+           {
+             if (TYPE_ANONYMOUS_P (nt))
+               error ("%qT is/uses anonymous type", t);
+             else
+               error ("template argument for %qD uses local type %qT",
+                      tmpl, t);
+           }
+         return true;
+       }
+      /* In order to avoid all sorts of complications, we do not
+        allow variably-modified types as template arguments.  */
+      else if (variably_modified_type_p (t, NULL_TREE))
        {
          if (complain & tf_error)
            error ("%qT is a variably modified type", t);
index 2d1378a..52a26bc 100644 (file)
@@ -1,3 +1,21 @@
+2009-11-02  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/other/linkage2.C: Move to...
+       * g++.dg/cpp0x/linkage2.C: ..here.
+       * g++.dg/abi/mangle32.C: Add -std=c++0x.
+       * g++.dg/cpp0x/nolinkage1.C: Likewise.
+       * g++.dg/debug/dwarf2/anonname1.C: Likewise.
+       * g++.dg/ext/anon-struct4.C: Revert earlier change.
+       * g++.dg/lookup/anon2.C: Likewise.
+       * g++.dg/other/anon3.C: Likewise.
+       * g++.dg/template/arg2.C: Likewise.
+       * g++.dg/template/local4.C: Likewise.
+       * g++.old-deja/g++.law/operators32.C: Likewise.
+       * g++.old-deja/g++.other/linkage2.C: Likewise.
+       * g++.old-deja/g++.pt/enum6.C: Likewise.
+       * g++.old-deja/g++.other/anon9.C: Likewise.
+       * g++.old-deja/g++.other/linkage1.C: Likewise.
+
 2009-11-02  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
        PR tree-optimization/41857
index de02887..244d074 100644 (file)
@@ -2,6 +2,9 @@
 
 // namespace-scope unnamed types have no linkage, so we only test that they
 // are distinct.
+
+// { dg-options -std=c++0x }
+
 typedef struct { } *A;
 typedef struct { } *B;
 
similarity index 97%
rename from gcc/testsuite/g++.dg/other/linkage2.C
rename to gcc/testsuite/g++.dg/cpp0x/linkage2.C
index 4e3e6f1..f41c21a 100644 (file)
@@ -4,6 +4,8 @@
 //   o the variable or function is not used (3.2 [basic.def.odr]) or is
 //   defined in the same translation unit.
 
+// { dg-options -std=c++0x }
+
 template <typename T> struct B {
   void g(T){}
   void h(T);                   // { dg-error "never defined" }
index a31394b..b69b6dd 100644 (file)
@@ -3,6 +3,7 @@
 
 // { dg-additional-sources "nolinkage1a.cc" }
 // { dg-do link }
+// { dg-options -std=c++0x }
 
 #include "nolinkage1.h"
 
index dcd2d8d..c9da2d6 100644 (file)
@@ -1,6 +1,6 @@
 // PR debug/41828
 // { dg-do compile }
-// { dg-options "-gdwarf-2 -dA" }
+// { dg-options "-gdwarf-2 -dA -std=c++0x" }
 // { dg-final { scan-assembler-not "<anonymous" } }
 // { dg-final { scan-assembler-not "\._\[0-9\]" } }
 // { dg-final { scan-assembler-not "\$_\[0-9\]" } }
index 53302d8..4f0fcd1 100644 (file)
@@ -1,3 +1,4 @@
 // PR c++/14401
 
 struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
+// { dg-warning "anonymous" "anon" { target *-*-* } 3 }
index 3143b62..d556ba0 100644 (file)
@@ -1,9 +1,9 @@
 // { dg-do compile }
 // { dg-options "" }
 
-// Make sure we don't issue a diagnostic if a type with no linkage is used
-// to declare a a variable that has linkage if that variable is defined.
+// Make sure we issue a diagnostic if a type with no linkage is used
+// to declare a a variable that has linkage.
 
-struct { int i; } a;
+struct { int i; } a; // { dg-warning "anonymous type" }
 
 void foo() { a.i; }
index 87cbfb5..87116eb 100644 (file)
@@ -4,4 +4,4 @@
 
 // { dg-do compile }
 
-enum { a = 3 } x;
+enum { a = 3 } x; // { dg-warning "anonymous type" }
index 1314b25..9fb7a68 100644 (file)
@@ -10,5 +10,5 @@ template <typename T> class X {};
 void fn ()
 {
   class L {};
-  X<L> f;
+  X<L> f; // { dg-error "uses local type|trying to instantiate|no type|invalid type" "" }
 }
index 41e2370..cfa3736 100644 (file)
@@ -4,5 +4,5 @@ template <typename T> void foo() {}
 
 int main () {
   struct S {};
-  foo<S> ();
+  foo<S> (); // { dg-error "match" } 
 }
index 89f0b66..91de03e 100644 (file)
@@ -49,7 +49,7 @@ foo() {std::cout << "foo created" << std::endl; }
 };
 
 foo **f2;
-allocate2d(d1, d2, f2);
-ffree(d1, f2);
+allocate2d(d1, d2, f2);// { dg-error "" }  type.*// ERROR -    trying to.*
+ffree(d1, f2);// { dg-error "" }  type.*// ERROR -    trying to.*
 
 }
index f4b1923..a364db8 100644 (file)
@@ -4,8 +4,3 @@
 
 typedef const struct { int i; } T; // { dg-error "" } referenced below
 void f (T* t);                 // { dg-error "" } uses unnamed type
-
-int main()
-{
-  f(0);
-}
index de9a6ac..e9b5a9d 100644 (file)
@@ -3,16 +3,13 @@ typedef struct {
   int i;
 } *p;
 
-void f (p) { }
-p q;
+void f (p) { }                 // { dg-error "uses anonymous type" }
+p q;                           // { dg-warning "uses anonymous type" } 
 
 int main()
 {
-  extern p j;                  // { dg-error "anonymous type" }
-  j+1;
+  extern p j;                  // { dg-warning "uses anonymous type" }
   struct A { int j; };
-  extern A a;                  // { dg-error "local type" }
-  a.j+1;
-  extern void f (A);           // { dg-error "local type" }
-  f(a);
+  extern A a;                  // { dg-warning "uses local type" }
+  extern void f (A);           // { dg-error "uses local type" }
 }
index 64f74f7..2385b22 100644 (file)
@@ -7,7 +7,7 @@ extern GDBM_FILE gdbm_open();
 }
 
 typedef struct { int dummy[10]; } *FAIL_FILE;
-extern FAIL_FILE fail_open(); // OK because it's never used
+extern FAIL_FILE fail_open(); // { dg-error "" } non-local function
 
 typedef struct { int dummy[10]; } *SUCCESS_FILE, S;
 extern SUCCESS_FILE success_open();
index 561254d..254b48b 100644 (file)
@@ -8,7 +8,7 @@ void fn(T)
 {
   enum tern { H, L, X, U };
 
-  vector<tern> ternvec;
+  vector<tern> ternvec; // { dg-error "" } composed from a local type
 }
 
 template void fn(int);