c++: Avoid ICE with dependent attribute on type.
authorJason Merrill <jason@redhat.com>
Mon, 27 Jan 2020 10:45:01 +0000 (05:45 -0500)
committerJason Merrill <jason@redhat.com>
Mon, 27 Apr 2020 21:21:56 +0000 (17:21 -0400)
We previously happened to accept this testcase, but never actually did
anything useful with the attribute.  The patch for PR86379 stopped using
TREE_TYPE as USING_DECL_SCOPE, so 'using A::b' no longer had TREE_TYPE set,
so the language-independent decl_attributes started crashing on it.

GNU attributes are more flexible in their placement than C++11 attributes,
so if we encounter a dependent GNU attribute that syntactically appertains
to a type rather than the declaration as a whole, move it to the
declaration; that's almost certainly what the user meant, anyway.

gcc/cp/ChangeLog
2020-04-27  Jason Merrill  <jason@redhat.com>

PR c++/90750
PR c++/79585
* decl.c (grokdeclarator): Move dependent attribute to decl.
* decl2.c (splice_template_attributes): No longer static.

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/testsuite/g++.dg/ext/attr-type1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wunused-var-26.C

index 8cb958f36fb14ce62024b79f626791ecf354552e..2b44b24461fd228d9093160fa7720c01d0df2fcf 100644 (file)
@@ -1,3 +1,10 @@
+2020-04-27  Jason Merrill  <jason@redhat.com>
+
+       PR c++/90750
+       PR c++/79585
+       * decl.c (grokdeclarator): Move dependent attribute to decl.
+       * decl2.c (splice_template_attributes): No longer static.
+
 2020-04-27  Patrick Palka  <ppalka@redhat.com>
 
        PR c++/94772
index 924c0b9c79076711b0a8fb45db9eb67f9d0fd8d8..fff0016b3aa2c196b20ad6b888c05285d2e27003 100644 (file)
@@ -6626,6 +6626,7 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
                       tree, bool, tree, tree);
 extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
                          tree, tree, tree);
+extern tree splice_template_attributes         (tree *, tree);
 extern bool any_dependent_type_attributes_p    (tree);
 extern tree cp_reconstruct_complex_type                (tree, tree);
 extern bool attributes_naming_typedef_ok       (tree);
index 31b5884ca3a917416670bd5fcdc3733e0910eda6..cf855dae9096859f49e81473fd0f2cfc04357e29 100644 (file)
@@ -11937,9 +11937,13 @@ grokdeclarator (const cp_declarator *declarator,
            attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
          if (declarator->kind == cdk_array)
            attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+         /* Assume that any attributes that get applied late to templates will
+            DTRT when applied to the declaration as a whole.  */
+         tree late_attrs = splice_template_attributes (&attrs, type);
          returned_attrs = decl_attributes (&type,
                                            chainon (returned_attrs, attrs),
                                            attr_flags);
+         returned_attrs = chainon (late_attrs, returned_attrs);
        }
 
       inner_declarator = declarator->declarator;
index 293df990435d5bdc67e7834b158b6149d32b8fc4..ac65529a01d1a036371483b4c43c80db4573532a 100644 (file)
@@ -1228,7 +1228,7 @@ is_late_template_attribute (tree attr, tree decl)
    the declaration itself is dependent, so all attributes should be applied
    at instantiation time.  */
 
-static tree
+tree
 splice_template_attributes (tree *attr_p, tree decl)
 {
   tree *p = attr_p;
diff --git a/gcc/testsuite/g++.dg/ext/attr-type1.C b/gcc/testsuite/g++.dg/ext/attr-type1.C
new file mode 100644 (file)
index 0000000..6e84ccc
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/90750
+// { dg-do compile { target c++11 } }
+
+template <typename> struct S
+{
+  static const int b = 64;
+};
+
+template <typename a> struct T: S<a>
+{
+  using A = S<a>;
+  using A::b;
+  char* __attribute__((aligned(b))) c;
+};
+
+T<int> t;
+
+#define SA(X) static_assert (X,#X)
+SA (alignof(T<int>) == S<int>::b);
index b3e020b600781f42b0b1123bd7f4911bfd79852d..89c53de88a4686f18fdaa754522d717e0d5aa882 100644 (file)
@@ -47,10 +47,10 @@ template <class T>
 void f_var_type_unused ()
 {
   // The variable's type is marked unused.
-  T* UNUSED t = new T;   // { dg-bogus "unused variable" "bug 79585" { xfail *-*-* } }
+  T* UNUSED t = new T;   // { dg-bogus "unused variable" "bug 79585" }
 
   typedef T U;
-  U* UNUSED u = new U;   // { dg-bogus "unused variable" "bug 79585" { xfail *-*-* } }
+  U* UNUSED u = new U;   // { dg-bogus "unused variable" "bug 79585" }
 
   typedef T UNUSED U;
   U v = U ();   // { dg-bogus "unused variable" "bug 79585" }