Bug 44906 - g++ is giving error: parse error in template argument list
Summary: g++ is giving error: parse error in template argument list
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.3
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2010-07-10 15:43 UTC by Amitava Ray Chaudhuri
Modified: 2021-08-04 15:36 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-08-03 00:00:00


Attachments
Code which is failing. (515 bytes, text/plain)
2010-07-10 15:44 UTC, Amitava Ray Chaudhuri
Details
.s file generated by -save-temps (30 bytes, text/plain)
2010-07-10 15:44 UTC, Amitava Ray Chaudhuri
Details
.ii file generated by -save-temps (73.98 KB, text/plain)
2010-07-10 15:45 UTC, Amitava Ray Chaudhuri
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Amitava Ray Chaudhuri 2010-07-10 15:43:04 UTC
amitavac@whileliesent-lm:~/data/prog/c++/template_ptr$g++ -v -o template template.cpp 
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 
COLLECT_GCC_OPTIONS='-v' '-o' 'template' '-shared-libgcc' '-mtune=generic' '-march=i486'
 /usr/lib/gcc/i486-linux-gnu/4.4.3/cc1plus -quiet -v -D_GNU_SOURCE template.cpp -D_FORTIFY_SOURCE=2 -quiet -dumpbase template.cpp -mtune=generic -march=i486 -auxbase template -version -fstack-protector -o /tmp/ccZiqQ9b.s
GNU C++ (Ubuntu 4.4.3-4ubuntu5) version 4.4.3 (i486-linux-gnu)
	compiled by GNU C version 4.4.3, GMP version 4.3.2, MPFR version 2.4.2-p1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/i486-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../i486-linux-gnu/include"
ignoring nonexistent directory "/usr/include/i486-linux-gnu"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/4.4
 /usr/include/c++/4.4/i486-linux-gnu
 /usr/include/c++/4.4/backward
 /usr/local/include
 /usr/lib/gcc/i486-linux-gnu/4.4.3/include
 /usr/lib/gcc/i486-linux-gnu/4.4.3/include-fixed
 /usr/include
End of search list.
GNU C++ (Ubuntu 4.4.3-4ubuntu5) version 4.4.3 (i486-linux-gnu)
	compiled by GNU C version 4.4.3, GMP version 4.3.2, MPFR version 2.4.2-p1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 35224f2c24023afb0a5be7befe8d5f3f
template.cpp: In member function ‘void MISC<T, P>::add(int)’:
template.cpp:55: error: parse error in template argument list
template.cpp:58: error: parse error in template argument list
template.cpp:61: error: parse error in template argument list
template.cpp:64: error: parse error in template argument list
template.cpp: In member function ‘void MISC<T, P>::print(int)’:
template.cpp:72: error: parse error in template argument list
template.cpp:75: error: parse error in template argument list
template.cpp:78: error: parse error in template argument list
template.cpp:81: error: parse error in template argument list

Following is the content of template.cpp (please let me know whats wrong with the following program):
#include<stdint.h>

#include<iostream>
#include<vector>
#include<set>

using namespace std;

template<typename T, typename P>
class MISC{
	private:
		vector<T> vec1;
		vector<T> vec2;

		set<T> st1;
		set<T> st2;

		vector<P> *ptr;
	private:
		template<vector<T>* vc>
			void addVecVals(){
				for(T i=0; i<10;i++)
				{
					vc->push_back(i);
				}
			}

		template<set<T>* st>
			void addStVals(){
				for(T i=0; i<10;i++)
				{
					st->insert(i);
				}
			}

		template<vector<T>* vc>
			void printVecVals(){
				for(typename vector<T>::iterator i=vc->begin(), j=vc->end(); i!=j;++i)
				{
					cout<<"val = "<<*i<<" , ";
				}
			}

		template<set<T>* st>
			void printStVals(){
				for(typename set<T>::iterator i=st->begin(), j=st->end(); i!=j;++i)
				{
					cout<<"val = "<<*i<<" , ";
				}
			}
	public:
		void add(int vecNum) {
			switch(vecNum) {
				case 0: //vecs.
					addVecVals<&vec1>();
					break;
				case 1:
					addVecVals<&vec2>();
					break;
				case 2: //sets
					addStVals<&st1>();
					break;
				case 3:
					addStVals<&st2>();
					break;
				default: break;
			}
		}
		void print(int vecNum) {
			switch(vecNum) {
				case 0: //vecs.
					printVecVals<&vec1>();
					break;
				case 1:
					printVecVals<&vec2>();
					break;
				case 2: //sets
					printStVals<&st1>();
					break;
				case 3:
					printStVals<&st2>();
					break;
				default: break;
			}
		}
};

int main(void) {
	MISC<uint64_t, double> m;
	m.add(0);
	m.add(1);
	m.add(2);
	m.add(3);
	return 0;
}
Comment 1 Amitava Ray Chaudhuri 2010-07-10 15:44:24 UTC
Created attachment 21176 [details]
Code which is failing.
Comment 2 Amitava Ray Chaudhuri 2010-07-10 15:44:57 UTC
Created attachment 21177 [details]
.s file generated by -save-temps
Comment 3 Amitava Ray Chaudhuri 2010-07-10 15:45:26 UTC
Created attachment 21178 [details]
.ii file generated by -save-temps
Comment 4 Andrew Pinski 2010-07-10 17:46:37 UTC
The error message is not clear.  The issue is that you are not using a constant expression for a template arugment.  Template arguments are either constant expressions or types.
Comment 5 Amitava Ray Chaudhuri 2010-07-10 18:45:48 UTC
(In reply to comment #4)
> The error message is not clear.  The issue is that you are not using a constant
> expression for a template arugment.  Template arguments are either constant
> expressions or types.
> 

Whenever I will be using this kind of template in a class, the variable name is predefined. Now when I create an object and call the function, it will get the address offset and thus should be able to create an instance of that function with same prototype but different body, else for such cases we have to create different functions for each member. 

Can it be a new feature in g++ compiler? This will make function and objects as first class citizen in C++. We can create function at runtime with different object embedded in it. (I know it can be done by #define, but this is a better way I think.)
Comment 6 Paolo Carlini 2010-07-10 22:19:30 UTC
Honestly, nothing similar will happen any time soon, it means changing completely the semantics of templates. Maybe we can produce a better diagnostics, let's add Manuel in CC to hear his opinion...
Comment 7 Paolo Carlini 2011-09-23 12:43:53 UTC
Closing as invalid.
Comment 8 Manuel López-Ibáñez 2011-09-23 13:59:07 UTC
(In reply to comment #6)
> Honestly, nothing similar will happen any time soon, it means changing
> completely the semantics of templates. Maybe we can produce a better
> diagnostics, let's add Manuel in CC to hear his opinion...

The code is invalid but the diagnostic could be much better (I only have GCC 4.5.2, so perhaps it is better in trunk).

Smaller testcase:

template<typename T>
class MISC{
public:
    T vec1;
    template<T* vc> void addVecVals(){};
    void add(void) { addVecVals<&vec1>();  };
};

void foo(void) {
    MISC<int> m;
    m.add();
}

Clang++ gives a somewhat better message:

/tmp/webcompile/_14512_0.cc:6:22: error: no matching member function for call to 'addVecVals'
    void add(void) { addVecVals<&vec1>();  };
                     ^~~~~~~~~~~~~~~~~
/tmp/webcompile/_14512_0.cc:11:7: note: in instantiation of member function 'MISC<int>::add' requested here
    m.add();
      ^
/tmp/webcompile/_14512_0.cc:5:26: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'vc'
    template<T* vc> void addVecVals(){};
                         ^
1 error generated.


I would argue for reopening it...
Comment 9 Paolo Carlini 2011-09-23 14:43:26 UTC
Hey, you woke up! ;) Sure, let's re-open is a diagnostic issue, your call.
Comment 10 Manuel López-Ibáñez 2011-10-19 22:24:12 UTC
The problem seems to be the tentative parsing in cp_parse_template_id, which tries every crazy thing it can, and when nothing works, it just gives this catch all diagnostic. 

But debugging the C++ parser is an absolute pain, I hope someone with more patience takes a shot at this. The current diagnostic is just awful.
Comment 11 Andrew Pinski 2021-08-04 06:20:43 UTC
For the testcase in comment #8:

Ok, this is interesting as at first I thought this was fixed in GCC 11 but then I looked to see what the different standards do as GCC 11's default is C++17.

With C++17 and C++20, we get:
<source>:8:34: error: use of 'this' in a constant expression
    8 |     void add(void) { addVecVals<&vec1>();  }
      |                                  ^~~~
<source>: In instantiation of 'void MISC<T>::add() [with T = int]':
<source>:13:10:   required from here
<source>:8:39: error: no matching function for call to 'MISC<int>::addVecVals<(&((MISC<int>*)this)->MISC<int>::vec1)>()'
    8 |     void add(void) { addVecVals<&vec1>();  }
      |                      ~~~~~~~~~~~~~~~~~^~
<source>:7:26: note: candidate: 'template<int* vc> void MISC<T>::addVecVals() [with T* vc = vc; T = int]'
    7 |     template<T* vc> void addVecVals(){}
      |                          ^~~~~~~~~~
<source>:7:26: note:   template argument deduction/substitution failed:
<source>:8:34: error: '&((MISC<int>*)this)->MISC<int>::vec1' is not a valid template argument of type 'int*' because '((MISC<int>*)this)->MISC<int>::vec1' is not a variable
    8 |     void add(void) { addVecVals<&vec1>();  }
      |                                  ^~~~


But for C++98, C++11, C++14, we get:
<source>: In member function 'void MISC<T>::add()':
<source>:8:22: error: parse error in template argument list
    8 |     void add(void) { addVecVals<&vec1>();  }
      |                      ^~~~~~~~~~~~~~~~~