Bug 52725 - [4.7/4.8 Regression] error: "capture of non-variable" for new-expression incorrectly parsed as lambda-expression
Summary: [4.7/4.8 Regression] error: "capture of non-variable" for new-expression inco...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P2 normal
Target Milestone: 4.7.1
Assignee: Jason Merrill
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2012-03-26 15:23 UTC by Joseph L
Modified: 2012-06-01 21:20 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.1.2, 4.4.3, 4.6.3
Known to fail:
Last reconfirmed: 2012-05-29 00:00:00


Attachments
the preprocessed file (230 bytes, application/octet-stream)
2012-03-26 15:23 UTC, Joseph L
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Joseph L 2012-03-26 15:23:51 UTC
Created attachment 26999 [details]
the preprocessed file

~/gcc-test$ g++-4.7.0 -o test -v -save-temps ItemIncGroup.cpp 
Using built-in specs.
COLLECT_GCC=g++-4.7.0
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/lto-wrapper
Target: i686-pc-linux-gnu
Configured with: ../configure --program-suffix=-4.7.0
Thread model: posix
gcc version 4.7.0 (GCC) 
COLLECT_GCC_OPTIONS='-o' 'test' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=pentiumpro'
 /usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/cc1plus -E -quiet -v -D_GNU_SOURCE ItemIncGroup.cpp -mtune=generic -march=pentiumpro -fpch-preprocess -o ItemIncGroup.ii
ignoring nonexistent directory "/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0
 /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/i686-pc-linux-gnu
 /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/backward
 /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/include
 /usr/local/include
 /usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/include-fixed
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-o' 'test' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=pentiumpro'
 /usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/cc1plus -fpreprocessed ItemIncGroup.ii -quiet -dumpbase ItemIncGroup.cpp -mtune=generic -march=pentiumpro -auxbase ItemIncGroup -version -o ItemIncGroup.s
GNU C++ (GCC) version 4.7.0 (i686-pc-linux-gnu)
	compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 2.4.2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++ (GCC) version 4.7.0 (i686-pc-linux-gnu)
	compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 2.4.2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: c256e2cdb5a4ae96bd7afc48ca236d31
ItemIncGroup.cpp: In member function ‘bool CItemIncGroup::SetIncrementalCountMax()’:
ItemIncGroup.cpp:7:38: error: capture of non-variable ‘CItemIncGroup::m_TotalIncrementalCount’ 
In file included from ItemIncGroup.cpp:3:0:
ItemIncGroup.h:17:18: note: ‘long int CItemIncGroup::m_TotalIncrementalCount’ declared here

Notes: Changing the type of m_pItemIncGroup from CItemInc to int will allow the code to compile. This code compiled with gcc 4.6.1.
Comment 1 Jonathan Wakely 2012-03-26 15:43:59 UTC
It works if you remove the parentheses, which also makes the code valid C++ (currently it relies on a GNU extension that allows a variable array size for a parenthesised new expression, you get a warning with -pedantic or -Wvla)

It seems that there's some interaction between the C++11 lambda parsing and the GNU extension
Comment 2 Steffen Möller 2012-05-25 10:33:51 UTC
Hello, I have something similar in the OpenMM code (https://simtk.org/home/openmm), with no ()s following the "new" as in


template <typename T>
struct CUDAStream : public SoADeviceObject
{
    unsigned int    _length;
    unsigned int    _subStreams;      # line 68
    unsigned int    _stride;
    T**             _pSysStream;
    T**             _pDevStream;
    T*              _pSysData;
    T*              _pDevData;
    std::string     _name;
    CUDAStream(int length, int subStreams = 1, std::string name="");
    CUDAStream(unsigned int length, unsigned int subStreams = 1, std::string name="");
    CUDAStream(unsigned int length, int subStreams = 1, std::string name="");
    CUDAStream(int length, unsigned int subStreams = 1, std::string name="");
    virtual ~CUDAStream();
    void Allocate();
    void Deallocate();
    void Upload();
    void Download();
    void CopyFrom(const CUDAStream<T>& src);
    void Collapse(unsigned int newstreams = 1, unsigned int interleave = 1);
    T& operator[](int index);
};

[...]

template <typename T>
void CUDAStream<T>::Allocate()
{
    cudaError_t status;
    _pSysStream =   new T*[_subStreams];                      # line 125
    _pDevStream =   new T*[_subStreams];
    _pSysData =     new T[_subStreams * _stride];

    status = cudaMalloc((void **) &_pDevData, _stride * _subStreams * sizeof(T));
    RTERROR(status, (_name+": cudaMalloc in CUDAStream::Allocate failed").c_str());

    for (unsigned int i = 0; i < _subStreams; i++)
    {
        _pSysStream[i] = _pSysData + i * _stride;
        _pDevStream[i] = _pDevData + i * _stride;
    }
}

for which 4.6.3 (Debian 4.6.3-5) happily crunches but 4.7 (Debian 4.7.0-9) gives me

cd /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/obj-x86_64-linux-gnu/platforms/cuda/sharedTarget && /usr/local/bin/c++   -DOpenMMCuda_EXPORTS -DOPENMM_LIBRARY_NAME=OpenMM -DOPENMM_MAJOR_VERSION=1 -DOPENMM_MINOR_VERSION=0 -DOPENMM_BUILD_VERSION=0 -DOPENMM_SVN_REVISION=\"exported\" -DOPENMM_COPYRIGHT_YEARS=\"2008\" -DOPENMM_AUTHORS=\"Peter.Eastman\" -O3 -DNDEBUG -fPIC -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/src -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/src -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/validate/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/reference/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/lbfgs/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/sfmt/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/lepton/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/quern/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/jama/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/olla/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/openmmapi/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/./include    -DOPENMMCUDA_BUILDING_SHARED_LIBRARY -o CMakeFiles/OpenMMCuda.dir/__/__/__/src/cuda/kApplyConstraints.cu_OpenMMCuda_generated.cpp.o -c /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/obj-x86_64-linux-gnu/src/cuda/kApplyConstraints.cu_OpenMMCuda_generated.cpp
/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h: In member function ‘virtual void CUDAStream<T>::Allocate()’:
/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:125:27: error: capture of non-variable ‘CUDAStream<T>::_subStreams’ 
/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:68:10: note: ‘unsigned int CUDAStream<T>::_subStreams’ declared here
/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:126:27: error: capture of non-variable ‘CUDAStream<T>::_subStreams’ 
/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:68:10: note: ‘unsigned int CUDAStream<T>::_subStreams’ declared here
make[3]: *** [platforms/cuda/sharedTarget/CMakeFiles/OpenMMCuda.dir/__/__/__/src/cuda/kApplyConstraints.cu_OpenMMCuda_generated.cpp.o] Error 1


Thanks and regards,

Steffen
Comment 3 Jonathan Wakely 2012-05-25 11:09:37 UTC
N.B. I've changed the Summary, the "non-variable" in the diagnostic refers to a non-automatic variable, in this case a data member, which isn't allowed in a lamdba capture. The problem is not that the error says a member variable is a non-variable, it's that a new-expression is mistaken for a lambda-expresion.


(In reply to comment #2)
> Hello, I have something similar in the OpenMM code
> (https://simtk.org/home/openmm), with no ()s following the "new" as in

Please provide a minimal, complete example, those snippets do not allow your report to be reproduced or confirmed.  This seems to be equivalent but works fine:

template <typename T>
struct CUDAStream
{
    unsigned int    _subStreams;
    T**             _pSysStream;
    void Allocate();
};

template <typename T>
void CUDAStream<T>::Allocate()
{
    _pSysStream =   new T*[_subStreams];
}
Comment 4 Steffen Möller 2012-05-29 10:33:36 UTC
Hello, this took me a while.

It seems like the problem is in (or in the interaction with) nvcc, the NVidia compiler. For that you program for the graphics card and the host processor at the same time. The .cu files indicate such files that are not meant to be seen by the regular compiler at a first sight. It then generates preprocessed files for gcc to digest.

$ rm -f t.cu_OpenMMCuda_generated.cpp; /usr/bin/nvcc t.cu -cuda -o t.cu_OpenMMCuda_generated.cpp && g++ -c t.cu_OpenMMCuda_generated.cpp
t.cu: In member function ‘void CUDAStream<T>::Allocate()’:
t.cu:12:27: error: capture of non-variable ‘CUDAStream<T>::_subStreams’ 
t.cu:4:10: note: ‘unsigned int CUDAStream<T>::_subStreams’ declared here

$ cat t.cu
template <typename T>
struct CUDAStream
{
    unsigned int    _subStreams;
    T**             _pSysStream;
    void Allocate();
};

template <typename T>
void CUDAStream<T>::Allocate()
{
    _pSysStream =   new T*[_subStreams];
}


The NVCC-generated code now has the ()s again:

# 9 "t.cu"
template< class T> void
# 10 "t.cu"
CUDAStream< T> ::Allocate()
# 11 "t.cu"
{
# 12 "t.cu"
(_pSysStream) = (new (T *[_subStreams]));
# 13 "t.cu"
}

4.6 crunges it, 4.7 does not. Sounds like we should prepare an email to NVidia. Anybody with any direct contacts?

Thanks

Steffen
Comment 5 Steffen Möller 2012-05-29 11:31:04 UTC
$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2012 NVIDIA Corporation
Built on Thu_Apr__5_00:24:31_PDT_2012
Cuda compilation tools, release 4.2, V0.2.1221

as shipping with Debian unstable in package version 4.2.9-1.
Comment 6 Jonathan Wakely 2012-05-29 11:55:06 UTC
Anything to do with the cuda compiler is irrelevant here, this report is for a GCC bug not for other programs, even if they generate code that triggers the bug.

Anyway, I'm confirming this, here's a reduced testcase that produces a slightly different eror, due to using a global instead of a data member:

struct A { };

extern int n;

void f()
{
    A** p = new (A*[n]);
}

Accepted by 4.6 and earlier, rejected by 4.7 and later

$ g++-4.7 -c t.cc
t.cc: In function 'void f()':
t.cc:7:21: warning: capture of variable 'n' with non-automatic storage duration [enabled by default]
t.cc:3:5: note: 'int n' declared here


N.B. 4.5 says

t.cc: In function ‘void f()’:
t.cc:7:19: warning: lambda expressions only available with -std=c++0x or -std=gnu++0x

But that was fixed for 4.6
Comment 7 Jonathan Wakely 2012-05-29 11:59:26 UTC
(In reply to comment #6)
> N.B. 4.5 says
> 
> t.cc: In function ‘void f()’:
> t.cc:7:19: warning: lambda expressions only available with -std=c++0x or
> -std=gnu++0x
> 
> But that was fixed for 4.6

I tested 4.5.2, that should be fixed in 4.5.3, see Bug 46159 and its dup Bug 47651
Comment 8 Jason Merrill 2012-06-01 21:19:26 UTC
Author: jason
Date: Fri Jun  1 21:19:22 2012
New Revision: 188127

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=188127
Log:
	PR c++/52725
	* parser.c (cp_parser_binary_expression): Bail early if we're parsing
	tentatively and the LHS has a parse error.

Added:
    trunk/gcc/testsuite/g++.dg/parse/new6.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/parser.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/template/sizeof-template-argument.C
Comment 9 Jason Merrill 2012-06-01 21:19:42 UTC
Author: jason
Date: Fri Jun  1 21:19:36 2012
New Revision: 188128

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=188128
Log:
	PR c++/52725
	* parser.c (cp_parser_binary_expression): Bail early if we're parsing
	tentatively and the LHS has a parse error.

Added:
    branches/gcc-4_7-branch/gcc/testsuite/g++.dg/parse/new6.C
Modified:
    branches/gcc-4_7-branch/gcc/cp/ChangeLog
    branches/gcc-4_7-branch/gcc/cp/parser.c
    branches/gcc-4_7-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_7-branch/gcc/testsuite/g++.dg/template/sizeof-template-argument.C
Comment 10 Jason Merrill 2012-06-01 21:20:19 UTC
Fixed for 4.7.1.