Hi again,

On 24/10/2017 20:58, Jason Merrill wrote:
This seems like an odd place to add the complete_type call.  What
happens if we change the COMPLETE_TYPE_P (type) in
cp_apply_type_quals_to_decl to COMPLETE_TYPE_P (complete_type (type))?
Finally I'm back with some information.

Simply doing the above doesn't fully work. The first symptom is the failure of g++.dg/init/mutable1.C which is precisely the testcase that you added together with the "|| !COMPLETE_TYPE_P (type)" itself: clearly, the additional condition isn't able anymore to do its work, because, first, when the type isn't complete, TYPE_HAS_MUTABLE_P (type) is false and then, when in fact it would be found true, we check !COMPLETE_TYPE_P (complete_type (type)) which is false, because completing succeeded.

Thus it seems we need at least something like:

   TREE_TYPE (decl) = type = complete_type (type);

   if (TYPE_HAS_MUTABLE_P (type) || !COMPLETE_TYPE_P (type))
     type_quals &= ~TYPE_QUAL_CONST;

But then, toward the end of the testsuite, we notice a more serious issue, which is unrelated to the above: g++.old-deja/g++.pt/poi1.C

// { dg-do assemble  }
// Origin: Gerald Pfeifer <pfei...@dbai.tuwien.ac.at>

template <class T>
class TLITERAL : public T
    {
    int x;
    };

class GATOM;

typedef TLITERAL<GATOM> x;
extern TLITERAL<GATOM> y;

also fails:

poi1.C: In instantiation of ‘class TLITERAL<GATOM>’:
poi1.C:13:24:   required from here
poi1.C:5:7: error: invalid use of incomplete type ‘class GATOM’
 class TLITERAL : public T
poi1.C:10:7: note: forward declaration of ‘class GATOM’
 class GATOM;

that is, trying to complete GATOM at the 'extern TLITERAL<GATOM> y;" line obviously fails. Note, in case isn't obvious, that this happens exactly for the cp_apply_type_quals_to_decl call at the end of grokdeclarator which I tried to change in my first try: the failure of poi1.C seems rather useful to figure out what we want to do for this bug.

Well, as expected, explicitly checking VAR_P && DECL_DECLARED_CONSTEXPR_P works again - it seems to me that after all it could make sense given the comment precisely talking about the additional complexities related to constexpr. Anyway, I'm attaching the corresponding complete patch.

Thanks!
Paolo.

/////////////////////
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 254071)
+++ cp/typeck.c (working copy)
@@ -9544,6 +9544,9 @@ cp_apply_type_quals_to_decl (int type_quals, tree
 
   /* If the type has (or might have) a mutable component, that component
      might be modified.  */
+  if (VAR_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
+    TREE_TYPE (decl) = type = complete_type (type);
+
   if (TYPE_HAS_MUTABLE_P (type) || !COMPLETE_TYPE_P (type))
     type_quals &= ~TYPE_QUAL_CONST;
 
Index: testsuite/g++.dg/cpp0x/constexpr-template11.C
===================================================================
--- testsuite/g++.dg/cpp0x/constexpr-template11.C       (nonexistent)
+++ testsuite/g++.dg/cpp0x/constexpr-template11.C       (working copy)
@@ -0,0 +1,16 @@
+// PR c++/65579
+// { dg-do link { target c++11 } }
+
+template <typename>
+struct S {
+    int i;
+};
+
+struct T {
+  static constexpr S<int> s = { 1 };
+};
+
+int main()
+{
+  return T::s.i;
+}

Reply via email to