From 7d4109231b2323ea3f1fe3ca66b7bbedd0508c69 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 27 May 2010 16:02:10 -0400 Subject: [PATCH] re PR c++/43555 (wrong address calculation of multidimensional variable-length array element) PR c++/43555 * decl.c (grokdeclarator) [cdk_pointer et al]: Force evaluation of anonymous VLA size. From-SVN: r159945 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/decl.c | 34 +++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/ext/vla9.C | 38 +++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 gcc/testsuite/g++.dg/ext/vla9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 75a53daced99..ad998d3db199 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2010-05-27 Jason Merrill + + PR c++/43555 + * decl.c (grokdeclarator) [cdk_pointer et al]: Force evaluation of + anonymous VLA size. + 2010-05-22 Release Manager * GCC 4.3.5 released. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c737169837ca..239bac337c09 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8248,6 +8248,40 @@ grokdeclarator (const cp_declarator *declarator, memfn_quals = TYPE_UNQUALIFIED; } + if (TREE_CODE (type) == FUNCTION_TYPE + && cp_type_quals (type) != TYPE_UNQUALIFIED) + error ("cannot declare %s to qualified function type %qT", + declarator->kind == cdk_reference ? "reference" : "pointer", + type); + + /* When the pointed-to type involves components of variable size, + care must be taken to ensure that the size evaluation code is + emitted early enough to dominate all the possible later uses + and late enough for the variables on which it depends to have + been assigned. + + This is expected to happen automatically when the pointed-to + type has a name/declaration of it's own, but special attention + is required if the type is anonymous. + + We handle the NORMAL and FIELD contexts here by inserting a + dummy statement that just evaluates the size at a safe point + and ensures it is not deferred until e.g. within a deeper + conditional context (c++/43555). + + We expect nothing to be needed here for PARM or TYPENAME. + Evaluating the size at this point for TYPENAME would + actually be incorrect, as we might be in the middle of an + expression with side effects on the pointed-to type size + "arguments" prior to the pointer declaration point and the + size evaluation could end up prior to the side effects. */ + + if (!TYPE_NAME (type) + && (decl_context == NORMAL || decl_context == FIELD) + && at_function_scope_p () + && variably_modified_type_p (type, NULL_TREE)) + finish_expr_stmt (TYPE_SIZE (type)); + if (declarator->kind == cdk_reference) { /* In C++0x, the type we are creating a reference to might be diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2f6bab9fd5c6..a646a165a3ea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-27 Jason Merrill + + PR c++/43555 + * g++.dg/ext/vla9.C: New. + 2010-05-22 Release Manager * GCC 4.3.5 released. diff --git a/gcc/testsuite/g++.dg/ext/vla9.C b/gcc/testsuite/g++.dg/ext/vla9.C new file mode 100644 index 000000000000..c58edbc9bd1b --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vla9.C @@ -0,0 +1,38 @@ +// PR c++/43555 +// { dg-options "" } +// { dg-do run } + +extern "C" void * malloc (__SIZE_TYPE__); +extern "C" int printf (const char *, ...); +extern "C" void abort(void); + +int nx,ny; + +void f(double *x1d,int choice) +{ + double (*x2d)[nx][ny]=(double(*)[nx][ny])x1d; + unsigned long delta; +// (*x2d)[0][0]=123; // <- this line affects the result + if (choice!=0) + { + delta=&(*x2d)[1][0]-x1d; + } + else + { + delta=&(*x2d)[1][0]-x1d; + } + printf("Choice: %d, Delta: %ld\n",choice,delta); + if (delta != ny) + abort (); +} + +int main() +{ + double *data; + nx=100; + ny=100; + data=(double*)malloc(nx*ny*sizeof(double)); + f(data,0); + f(data,1); + return 0; +} -- 2.47.2