re PR c++/55250 ([C++0x] enum declarations within constexpr function are allowed, constexpr declarations are not)
/cp 2014-10-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/55250 * semantics.c (check_constexpr_bind_expr_vars): New. (check_constexpr_ctor_body, massage_constexpr_body): Use it. (build_constexpr_constructor_member_initializers): Handle BIND_EXPR in the main conditional. /testsuite 2014-10-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/55250 * g++.dg/cpp0x/constexpr-type-decl1.C: New. * g++.dg/cpp0x/constexpr-type-def1.C: Likewise. * g++.dg/cpp1y/constexpr-type-def1.C: Likewise. From-SVN: r215954
This commit is contained in:
parent
c4b64f5bca
commit
fbf833b776
@ -1,3 +1,11 @@
|
||||
2014-10-06 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/55250
|
||||
* semantics.c (check_constexpr_bind_expr_vars): New.
|
||||
(check_constexpr_ctor_body, massage_constexpr_body): Use it.
|
||||
(build_constexpr_constructor_member_initializers): Handle
|
||||
BIND_EXPR in the main conditional.
|
||||
|
||||
2014-10-02 Mark Wielaard <mjw@redhat.com>
|
||||
|
||||
PR debug/63239
|
||||
|
@ -7833,6 +7833,25 @@ build_data_member_initialization (tree t, vec<constructor_elt, va_gc> **vec)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Subroutine of check_constexpr_ctor_body and massage_constexpr_body.
|
||||
In C++11 mode checks that the TYPE_DECLs in the BIND_EXPR_VARS of a
|
||||
BIND_EXPR conform to 7.1.5/3/4 on typedef and alias declarations. */
|
||||
|
||||
static bool
|
||||
check_constexpr_bind_expr_vars (tree t)
|
||||
{
|
||||
gcc_assert (TREE_CODE (t) == BIND_EXPR);
|
||||
|
||||
if (cxx_dialect >= cxx14)
|
||||
return true;
|
||||
|
||||
for (tree var = BIND_EXPR_VARS (t); var; var = DECL_CHAIN (var))
|
||||
if (TREE_CODE (var) == TYPE_DECL
|
||||
&& DECL_IMPLICIT_TYPEDEF_P (var))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Make sure that there are no statements after LAST in the constructor
|
||||
body represented by LIST. */
|
||||
|
||||
@ -7850,7 +7869,7 @@ check_constexpr_ctor_body (tree last, tree list)
|
||||
break;
|
||||
if (TREE_CODE (t) == BIND_EXPR)
|
||||
{
|
||||
if (BIND_EXPR_VARS (t))
|
||||
if (!check_constexpr_bind_expr_vars (t))
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
@ -7860,8 +7879,6 @@ check_constexpr_ctor_body (tree last, tree list)
|
||||
else
|
||||
continue;
|
||||
}
|
||||
/* We currently allow typedefs and static_assert.
|
||||
FIXME allow them in the standard, too. */
|
||||
if (TREE_CODE (t) != STATIC_ASSERT)
|
||||
{
|
||||
ok = false;
|
||||
@ -7964,6 +7981,8 @@ build_constexpr_constructor_member_initializers (tree type, tree body)
|
||||
"a function-try-block");
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (TREE_CODE (body) == BIND_EXPR)
|
||||
ok = build_data_member_initialization (BIND_EXPR_BODY (body), &vec);
|
||||
else if (EXPR_P (body))
|
||||
ok = build_data_member_initialization (body, &vec);
|
||||
else
|
||||
@ -8055,7 +8074,8 @@ massage_constexpr_body (tree fun, tree body)
|
||||
body = EH_SPEC_STMTS (body);
|
||||
if (TREE_CODE (body) == MUST_NOT_THROW_EXPR)
|
||||
body = TREE_OPERAND (body, 0);
|
||||
if (TREE_CODE (body) == BIND_EXPR)
|
||||
if (TREE_CODE (body) == BIND_EXPR
|
||||
&& check_constexpr_bind_expr_vars (body))
|
||||
body = BIND_EXPR_BODY (body);
|
||||
body = constexpr_fn_retval (body);
|
||||
}
|
||||
|
@ -1,3 +1,10 @@
|
||||
2014-10-06 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/55250
|
||||
* g++.dg/cpp0x/constexpr-type-decl1.C: New.
|
||||
* g++.dg/cpp0x/constexpr-type-def1.C: Likewise.
|
||||
* g++.dg/cpp1y/constexpr-type-def1.C: Likewise.
|
||||
|
||||
2014-10-06 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
* c-c++-common/raw-string-3.c: Use -std=gnu89 for C.
|
||||
|
58
gcc/testsuite/g++.dg/cpp0x/constexpr-type-decl1.C
Normal file
58
gcc/testsuite/g++.dg/cpp0x/constexpr-type-decl1.C
Normal file
@ -0,0 +1,58 @@
|
||||
// PR c++/55250
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
#define SA(X) static_assert((X),#X)
|
||||
|
||||
struct GS { constexpr operator int() { return 1; } };
|
||||
enum GE { y = 1 };
|
||||
|
||||
constexpr int Test1(int x) { typedef int T; return T(x) + 1; }
|
||||
constexpr int Test2(int x) { using T = int; return T(x) + 1; }
|
||||
constexpr int Test3(int x) { typedef GS T; return x + T(); }
|
||||
constexpr int Test4(int x) { using T = GS; return x + T(); }
|
||||
constexpr int Test5(int x) { typedef GE T; return x + T::y; }
|
||||
constexpr int Test6(int x) { using T = GE; return x + T::y; }
|
||||
|
||||
SA(Test1(2) == 3);
|
||||
SA(Test2(2) == 3);
|
||||
SA(Test3(2) == 3);
|
||||
SA(Test4(2) == 3);
|
||||
SA(Test5(2) == 3);
|
||||
SA(Test6(2) == 3);
|
||||
|
||||
struct S1
|
||||
{
|
||||
constexpr S1() { typedef int T; SA(T(1) == 1); }
|
||||
};
|
||||
|
||||
struct S2
|
||||
{
|
||||
constexpr S2() { using T = int; SA(T(1) == 1); }
|
||||
};
|
||||
|
||||
struct S3
|
||||
{
|
||||
constexpr S3() { typedef GS T; SA(T() == 1); }
|
||||
};
|
||||
|
||||
struct S4
|
||||
{
|
||||
constexpr S4() { using T = GS; SA(T() == 1); }
|
||||
};
|
||||
|
||||
struct S5
|
||||
{
|
||||
constexpr S5() { typedef GE T; SA(T::y == 1); }
|
||||
};
|
||||
|
||||
struct S6
|
||||
{
|
||||
constexpr S6() { using T = GE; SA(T::y == 1); }
|
||||
};
|
||||
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
S3 s3;
|
||||
S4 s4;
|
||||
S5 s5;
|
||||
S6 s6;
|
44
gcc/testsuite/g++.dg/cpp0x/constexpr-type-def1.C
Normal file
44
gcc/testsuite/g++.dg/cpp0x/constexpr-type-def1.C
Normal file
@ -0,0 +1,44 @@
|
||||
// PR c++/55250
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
constexpr int Test1(int x) { enum E { y = 1 }; return x; } // { dg-error "not a return-statement" "" { target { c++11_only } } }
|
||||
|
||||
constexpr int Test2(int x) { struct T { }; return x; } // { dg-error "not a return-statement" "" { target { c++11_only } } }
|
||||
|
||||
constexpr int Test3(int x) { typedef enum E { y = 1 } EE; return x; } // { dg-error "not a return-statement" "" { target { c++11_only } } }
|
||||
|
||||
constexpr int Test4(int x) { typedef struct T { } TT; return x; } // { dg-error "not a return-statement" "" { target { c++11_only } } }
|
||||
|
||||
constexpr int Test5(int x) { using EE = enum E { y = 1 }; return x; } // { dg-error "not a return-statement" "" { target { c++11_only } } }
|
||||
|
||||
constexpr int Test6(int x) { using TT = struct T { }; return x; } // { dg-error "not a return-statement" "" { target { c++11_only } } }
|
||||
|
||||
struct S1
|
||||
{
|
||||
constexpr S1() { enum E { y = 1 }; } // { dg-error "does not have empty body" "" { target { c++11_only } } }
|
||||
};
|
||||
|
||||
struct S2
|
||||
{
|
||||
constexpr S2() { struct T { }; } // { dg-error "does not have empty body" "" { target { c++11_only } } }
|
||||
};
|
||||
|
||||
struct S3
|
||||
{
|
||||
constexpr S3() { typedef enum E { y = 1 } EE; } // { dg-error "does not have empty body" "" { target { c++11_only } } }
|
||||
};
|
||||
|
||||
struct S4
|
||||
{
|
||||
constexpr S4() { typedef struct T { } TT; } // { dg-error "does not have empty body" "" { target { c++11_only } } }
|
||||
};
|
||||
|
||||
struct S5
|
||||
{
|
||||
constexpr S5() { using EE = enum E { y = 1 }; } // { dg-error "does not have empty body" "" { target { c++11_only } } }
|
||||
};
|
||||
|
||||
struct S6
|
||||
{
|
||||
constexpr S6() { using TT = struct T { }; } // { dg-error "does not have empty body" "" { target { c++11_only } } }
|
||||
};
|
60
gcc/testsuite/g++.dg/cpp1y/constexpr-type-def1.C
Normal file
60
gcc/testsuite/g++.dg/cpp1y/constexpr-type-def1.C
Normal file
@ -0,0 +1,60 @@
|
||||
// PR c++/55250
|
||||
// { dg-do compile { target c++14 } }
|
||||
|
||||
#define SA(X) static_assert((X),#X)
|
||||
|
||||
constexpr int Test1(int x) { enum E { y = 1 }; return x + y; }
|
||||
|
||||
constexpr int Test2(int x) { struct T { constexpr operator int() { return 1; } }; return x + T(); }
|
||||
|
||||
constexpr int Test3(int x) { typedef enum E { y = 1 } EE; return x + EE::y; }
|
||||
|
||||
constexpr int Test4(int x) { typedef struct T { constexpr operator int() { return 1; } } TT; return x + TT(); }
|
||||
|
||||
constexpr int Test5(int x) { using EE = enum E { y = 1 }; return x + EE::y; }
|
||||
|
||||
constexpr int Test6(int x) { using TT = struct T { constexpr operator int() { return 1; } }; return x + TT(); }
|
||||
|
||||
SA(Test1(2) == 3);
|
||||
SA(Test2(2) == 3);
|
||||
SA(Test3(2) == 3);
|
||||
SA(Test4(2) == 3);
|
||||
SA(Test5(2) == 3);
|
||||
SA(Test6(2) == 3);
|
||||
|
||||
struct S1
|
||||
{
|
||||
constexpr S1() { enum E { y = 1 }; SA(y == 1); }
|
||||
};
|
||||
|
||||
struct S2
|
||||
{
|
||||
constexpr S2() { struct T { constexpr operator int() { return 1; } }; SA(T() == 1); }
|
||||
};
|
||||
|
||||
struct S3
|
||||
{
|
||||
constexpr S3() { typedef enum E { y = 1} EE; SA(EE::y == 1); }
|
||||
};
|
||||
|
||||
struct S4
|
||||
{
|
||||
constexpr S4() { typedef struct T { constexpr operator int() { return 1; } } TT; SA(TT() == 1); }
|
||||
};
|
||||
|
||||
struct S5
|
||||
{
|
||||
constexpr S5() { using EE = enum E { y = 1}; SA(EE::y == 1); }
|
||||
};
|
||||
|
||||
struct S6
|
||||
{
|
||||
constexpr S6() { using TT = struct T { constexpr operator int() { return 1; } }; SA(TT() == 1); }
|
||||
};
|
||||
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
S3 s3;
|
||||
S4 s4;
|
||||
S5 s5;
|
||||
S6 s6;
|
Loading…
Reference in New Issue
Block a user