Skip to content

Commit aee78c5

Browse files
committed
add function tests, simplify
1 parent cd750c9 commit aee78c5

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5262,8 +5262,7 @@ static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
52625262

52635263
// For references to objects, check they do not designate a one-past-the-end
52645264
// object.
5265-
if (VD->getType()->isReferenceType() &&
5266-
!VD->getType()->isFunctionReferenceType()) {
5265+
if (VD->getType()->isReferenceType()) {
52675266
return EvaluateInitForDeclOfReferenceType(Info, VD, InitE, Result, Val);
52685267
} else if (!EvaluateInPlace(Val, Info, Result, InitE)) {
52695268
// Wipe out any partially-computed value, to allow tracking that this
@@ -10965,8 +10964,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
1096510964
isa<CXXDefaultInitExpr>(Init));
1096610965

1096710966
APValue &FieldVal = Result.getStructField(Field->getFieldIndex());
10968-
if (Field->getType()->isReferenceType() &&
10969-
!Field->getType()->isFunctionReferenceType()) {
10967+
if (Field->getType()->isReferenceType()) {
1097010968
LValue Result;
1097110969
if (!EvaluateInitForDeclOfReferenceType(Info, Field, Init, Result,
1097210970
FieldVal)) {

clang/test/SemaCXX/constant-expression-cxx14.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,4 +1389,59 @@ constexpr bool test_ctr(int *i) {
13891389
static_assert(test_ctr(nullptr), ""); // expected-note {{in call to 'test_ctr(nullptr)'}}
13901390
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
13911391

1392+
1393+
// verify that we can dereference function pointers
1394+
namespace functions {
1395+
1396+
constexpr int f() {return 0;}
1397+
constexpr int(*f_ptr)() = &f;
1398+
constexpr int(*null_ptr)() = nullptr;
1399+
1400+
constexpr int(&f_ref)() = f;
1401+
constexpr int test = (*f_ptr)();
1402+
constexpr int test2 = (*f_ref)();
1403+
constexpr int test3 = (*f_ref)();
1404+
constexpr int test4 = (*null_ptr)();
1405+
//expected-error@-1 {{constexpr variable 'test4' must be initialized by a constant expression}} \
1406+
//expected-note@-1 {{'(*null_ptr)' evaluates to a null function pointer}}
1407+
1408+
constexpr int(*f_ptr_arr[1])() = {&f};
1409+
constexpr int test_array_ok = (f_ptr_arr[0])();
1410+
constexpr int test_array_err = (f_ptr_arr[1])();
1411+
// expected-error@-1 {{constexpr variable 'test_array_err' must be initialized by a constant expression}} \
1412+
// expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
1413+
1414+
struct S {
1415+
int(*f_ptr)() = &f;
1416+
int(*f_ptr_arr[1])() = {&f};
1417+
int(&f_ref)() = f;
1418+
int(*null_ptr)() = nullptr;
1419+
};
1420+
1421+
constexpr int test_member() {
1422+
S s {};
1423+
(*s.f_ptr)();
1424+
(*s.f_ref)();
1425+
(s.f_ref)();
1426+
(s.f_ptr_arr[0])();
1427+
(s.f_ptr_arr[1])();
1428+
// expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
1429+
return 0;
1430+
}
1431+
constexpr int test_member_null() { // cxx14_20-error {{never produces a constant expression}}
1432+
S s {};
1433+
(*s.null_ptr)(); // expected-note {{'(*s.null_ptr)' evaluates to a null function pointer}} \
1434+
// cxx14_20-note {{'(*s.null_ptr)' evaluates to a null function pointer}}
1435+
return 0;
1436+
}
1437+
1438+
static_assert(test_member(), "");
1439+
// expected-error@-1 {{static assertion expression is not an integral constant expression}} \
1440+
// expected-note@-1 {{in call to 'test_member()'}}
1441+
1442+
static_assert(test_member_null(), "");
1443+
// expected-error@-1 {{static assertion expression is not an integral constant expression}} \
1444+
// expected-note@-1 {{in call to 'test_member_null()'}}
1445+
1446+
}
13921447
}

0 commit comments

Comments
 (0)