re PR c++/35546 (__attribute__(format...) broken for members of template classes?)
authorJakub Jelinek <jakub@redhat.com>
Wed, 26 Mar 2008 20:34:14 +0000 (21:34 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 26 Mar 2008 20:34:14 +0000 (21:34 +0100)
PR c++/35546
* pt.c (apply_late_template_attributes): Don't call tsubst on
first attribute argument if it is IDENTIFIER_NODE.

* g++.dg/ext/attrib33.C: New test.

From-SVN: r133615

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/attrib33.C [new file with mode: 0644]

index 60eb1a35b9faff4222ad480b8173886d7682ebd7..447bfc04117cd0b62052f3a20897bb02d9fcf4f8 100644 (file)
@@ -1,5 +1,9 @@
 2008-03-26  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/35546
+       * pt.c (apply_late_template_attributes): Don't call tsubst on
+       first attribute argument if it is IDENTIFIER_NODE.
+
        PR c++/35332
        * error.c (dump_expr): Pass {,UN}ORDERED_EXPR, UN{LT,LE,GT,GE,EQ}_EXPR
        and LTGT_EXPR to pp_expression.
index 67d392da456f778d5d80a951a45891bc67789b75..6f7efa6e55ea5e924565db784081cc4b78d6433d 100644 (file)
@@ -6791,9 +6791,29 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
            {
              *p = TREE_CHAIN (t);
              TREE_CHAIN (t) = NULL_TREE;
-             TREE_VALUE (t)
-               = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
-                              /*integral_constant_expression_p=*/false);
+             /* If the first attribute argument is an identifier, don't
+                pass it through tsubst.  Attributes like mode, format,
+                cleanup and several target specific attributes expect it
+                unmodified.  */
+             if (TREE_VALUE (t)
+                 && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
+                 && TREE_VALUE (TREE_VALUE (t))
+                 && (TREE_CODE (TREE_VALUE (TREE_VALUE (t)))
+                     == IDENTIFIER_NODE))
+               {
+                 tree chain
+                   = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
+                                  in_decl,
+                                  /*integral_constant_expression_p=*/false);
+                 if (chain != TREE_CHAIN (TREE_VALUE (t)))
+                   TREE_VALUE (t)
+                     = tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)),
+                                  chain);
+               }
+             else
+               TREE_VALUE (t)
+                 = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
+                                /*integral_constant_expression_p=*/false);
              *q = t;
              q = &TREE_CHAIN (t);
            }
index 0ad8102a7eefe66240ae7a2deded3bc333c50142..fda355c021769a040e4475bf8efd367256dce51c 100644 (file)
@@ -1,3 +1,8 @@
+2008-03-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/35546
+       * g++.dg/ext/attrib33.C: New test.
+
 2008-03-26  Richard Guenther  <rguenther@suse.de>
 
        Revert
diff --git a/gcc/testsuite/g++.dg/ext/attrib33.C b/gcc/testsuite/g++.dg/ext/attrib33.C
new file mode 100644 (file)
index 0000000..5b98984
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/35546
+// { dg-do compile }
+
+template <int N>
+struct T
+{
+  void foo (char const * ...) __attribute__ ((format (printf,2,3)));
+};
+
+template struct T<3>;
+
+template <typename T>
+struct U
+{
+  typedef T __attribute__((mode (SI))) V;
+};
+
+U<int>::V v;