Skip to content

Commit f0f7516

Browse files
committed
Handle const pointers
1 parent f2e794e commit f0f7516

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

‎lib/templatesimplifier.cpp‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,9 @@ static DeducedType valueTypeToDeducedType(const ValueType* vt, const ParameterSh
930930
return DeducedType();
931931
constness &= ~(1U << pointer);
932932
--pointer;
933+
// "const T *": the parameter provides the const of the pointee
934+
if (shape.isConst)
935+
constness &= ~(1U << pointer);
933936
} else if (!shape.isReference || shape.isConst) {
934937
// "T" and "const T &" deduction drops the top level const
935938
constness &= ~(1U << pointer);

‎test/testcondition.cpp‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ class TestCondition : public TestFixture {
129129
TEST_CASE(knownConditionAfterBailout); // #12526
130130
TEST_CASE(knownConditionIncDecOperator);
131131
TEST_CASE(knownConditionFloating);
132+
TEST_CASE(knownConditionTemplateConstPointer); // "const T *" must deduce T without the const
132133
}
133134

134135
struct CheckOptions
@@ -6917,6 +6918,20 @@ class TestCondition : public TestFixture {
69176918
"",
69186919
errout_str());
69196920
}
6921+
6922+
void knownConditionTemplateConstPointer() {
6923+
// the deduced T must be "int", not "const int" - otherwise the local s is a constant
6924+
check("template<class T> T sum(const T* p, int n) {\n"
6925+
" T s = 0;\n"
6926+
" for (int i = 0; i < n; ++i)\n"
6927+
" s += p[i];\n"
6928+
" if (s == 0)\n"
6929+
" return -1;\n"
6930+
" return s;\n"
6931+
"}\n"
6932+
"int g(const int* p, int n) { return sum(p, n); }\n");
6933+
ASSERT_EQUALS("", errout_str());
6934+
}
69206935
};
69216936

69226937
REGISTER_TEST(TestCondition)

‎test/testsimplifytemplate.cpp‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ class TestSimplifyTemplate : public TestFixture {
317317
TEST_CASE(templateTypeDeductionMultiPass); // a pending deduction survives later simplifier passes
318318
TEST_CASE(templateTypeDeductionEnum); // enum arguments deduce the enum, not its underlying type
319319
TEST_CASE(templateTypeDeductionArray); // array arguments: only the decayed dimension is a pointer
320+
TEST_CASE(templateTypeDeductionConstPointer); // "const T *": the parameter provides the pointee const
320321

321322
TEST_CASE(simplifyTemplateArgs1);
322323
TEST_CASE(simplifyTemplateArgs2);
@@ -7376,6 +7377,58 @@ class TestSimplifyTemplate : public TestFixture {
73767377
ASSERT_EQUALS("", errout_str());
73777378
}
73787379

7380+
void templateTypeDeductionConstPointer()
7381+
{
7382+
{ // T must not include the const that the parameter already provides, otherwise
7383+
// every T local of the instantiation becomes a constant
7384+
const char code[] = "template<class T> T sum(const T* p, int n) {\n"
7385+
" T s = 0;\n"
7386+
" for (int i = 0; i < n; ++i)\n"
7387+
" s += p[i];\n"
7388+
" return s;\n"
7389+
"}\n"
7390+
"int g(const int* p, int n) { return sum(p, n); }";
7391+
const char exp[] = "int sum<int> ( const int * p , int n ) ; "
7392+
"int g ( const int * p , int n ) { return sum<int> ( p , n ) ; } "
7393+
"int sum<int> ( const int * p , int n ) { "
7394+
"int s ; s = 0 ; "
7395+
"for ( int i = 0 ; i < n ; ++ i ) { "
7396+
"s += p [ i ] ; "
7397+
"} "
7398+
"return s ; "
7399+
"}";
7400+
ASSERT_EQUALS(exp, tok(code));
7401+
ASSERT_EQUALS("", errout_str());
7402+
}
7403+
{ // the const at the other pointer levels is part of T
7404+
const char code[] = "template<class T> void f(const T* p) {}\n"
7405+
"template<class T> void h(T* p) {}\n"
7406+
"void g(const int* a, int* b, const int** c, int* const* d, const char* const e) {\n"
7407+
" f(a); f(b); f(c); f(d); f(e); h(a); h(b); h(d);\n"
7408+
"}";
7409+
const char exp[] = "void f<int> ( const int * p ) ; "
7410+
"void f<constint*> ( const int * const * p ) ; "
7411+
"void f<int*> ( int * const * p ) ; "
7412+
"void f<char> ( const char * p ) ; "
7413+
"void h<constint> ( const int * p ) ; "
7414+
"void h<int> ( int * p ) ; "
7415+
"void h<int*const> ( int * const * p ) ; "
7416+
"void g ( const int * a , int * b , const int * * c , int * const * d , const char * const e ) { "
7417+
"f<int> ( a ) ; f<int> ( b ) ; f<constint*> ( c ) ; f<int*> ( d ) ; f<char> ( e ) ; "
7418+
"h<constint> ( a ) ; h<int> ( b ) ; h<int*const> ( d ) ; "
7419+
"} "
7420+
"void h<constint> ( const int * p ) { } "
7421+
"void h<int> ( int * p ) { } "
7422+
"void h<int*const> ( int * const * p ) { } "
7423+
"void f<int> ( const int * p ) { } "
7424+
"void f<constint*> ( const int * const * p ) { } "
7425+
"void f<int*> ( int * const * p ) { } "
7426+
"void f<char> ( const char * p ) { }";
7427+
ASSERT_EQUALS(exp, tok(code));
7428+
ASSERT_EQUALS("", errout_str());
7429+
}
7430+
}
7431+
73797432
void simplifyTemplateArgs1() {
73807433
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < ( 2 ) >;\n"));
73817434
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < 1 + 1 >;\n"));

0 commit comments

Comments
 (0)