Another case that breaks with my fix for PR90750: we shouldn't move type
attributes in TYPENAME context either, as there's no decl for them to move
to.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog:

        PR c++/95222
        * decl.c (grokdeclarator): Don't shift attributes in TYPENAME
        context.

gcc/testsuite/ChangeLog:

        PR c++/95222
        * g++.dg/ext/tmplattr10.C: New test.
---
 gcc/cp/decl.c                         |  2 +-
 gcc/testsuite/g++.dg/ext/tmplattr10.C | 52 +++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/tmplattr10.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2e1390837e8..5476965996b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11951,7 +11951,7 @@ grokdeclarator (const cp_declarator *declarator,
          if (declarator->kind == cdk_array)
            attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
          tree late_attrs = NULL_TREE;
-         if (decl_context != PARM)
+         if (decl_context != PARM && decl_context != TYPENAME)
            /* Assume that any attributes that get applied late to
               templates will DTRT when applied to the declaration
               as a whole.  */
diff --git a/gcc/testsuite/g++.dg/ext/tmplattr10.C 
b/gcc/testsuite/g++.dg/ext/tmplattr10.C
new file mode 100644
index 00000000000..3fb8c21ccbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/tmplattr10.C
@@ -0,0 +1,52 @@
+// PR c++/95222
+// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } }
+
+#if defined(_MSC_VER)
+#define CC_FASTCALL __fastcall
+#define CC_STDCALL __stdcall
+#else
+#define CC_FASTCALL __attribute__((fastcall))
+#define CC_STDCALL __attribute__((stdcall))
+#endif
+
+template <typename FuncT>
+struct FuncResult;
+
+template <typename R, typename... Args>
+struct FuncResult<R(*)(Args...)>
+{
+    using type = R;
+};
+
+template <typename R, typename... Args>
+struct FuncResult<R(CC_FASTCALL*)(Args...)>
+{
+    using type = R;
+};
+
+template <typename R, typename... Args>
+struct FuncResult<R(CC_STDCALL*)(Args...)>
+{
+    using type = R;
+};
+
+template <typename FuncT>
+auto wrap(FuncT f) -> typename FuncResult<FuncT>::type
+{
+    return f(1, 2, 3);
+}
+
+int CC_FASTCALL func1(int x, int y, int z)
+{
+    return x + y + z;
+}
+
+int CC_STDCALL func2(int x, int y, int z)
+{
+    return x + y + z;
+}
+
+int main()
+{
+    return wrap(&func1) + wrap(&func2);
+}

base-commit: ac9face8d26ea4b6aa72902ecc22e89ef00763c5
-- 
2.18.1

Reply via email to