In r233563 (where I applied the 2nd version of the fix for PR c++/68948) I shouldn't have reverted the original fix because it is still required for diagnosing an invalid constructor call with dependent arguments (because in that case we delay further processing of the call until instantiation). Otherwise we end up with an error_mark_node in place of the constructor call without ever emitting an error message.
This patch adds back in the check in tsubst_baselink which was removed. One minor caveat about this check is that it emits an error instead of a permerror because I'm not sure how to correctly recover from this error here. Bootstrapped and tested on x86_64-pc-linux gnu. Does this look ok to commit? gcc/cp/ChangeLog: PR c++/68948 PR c++/69961 * pt.c (tsubst_baselink): Reinstate the check for an invalid constructor call. gcc/testsuite/ChangeLog: PR c++/69961 * g++.dg/template/pr69961a.C: New test. * g++.dg/template/pr69961b.C: New test. --- gcc/cp/pt.c | 10 +++++++++- gcc/testsuite/g++.dg/template/pr69961a.C | 25 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/template/pr69961b.C | 15 +++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/template/pr69961a.C create mode 100644 gcc/testsuite/g++.dg/template/pr69961b.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 12cb788..a7d2288 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13607,7 +13607,15 @@ tsubst_baselink (tree baselink, tree object_type, name = mangle_conv_op_name_for_type (optype); baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1); if (!baselink) - return error_mark_node; + { + if (constructor_name_p (name, qualifying_scope)) + { + if (complain & tf_error) + error ("cannot call constructor %<%T::%D%> directly", + qualifying_scope, name); + } + return error_mark_node; + } /* If lookup found a single function, mark it as used at this point. (If it lookup found multiple functions the one selected diff --git a/gcc/testsuite/g++.dg/template/pr69961a.C b/gcc/testsuite/g++.dg/template/pr69961a.C new file mode 100644 index 0000000..b0c5d41 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr69961a.C @@ -0,0 +1,25 @@ +// PR c++/69961 +// { dg-do compile { target c++11 } } + +#include <string> + +using std::string; + +class Format { + public: + explicit Format(string formatted) {} + string buffer; +}; + +string StrCat(const string& a) { + return ""; +} + +template <typename... AV> +Format Message(string msg, const AV&... args) { + return Format::Format(StrCat(msg, args...)); // { dg-error "cannot call constructor" } +} + +int main(int, char**) { + Message("msg"); +} diff --git a/gcc/testsuite/g++.dg/template/pr69961b.C b/gcc/testsuite/g++.dg/template/pr69961b.C new file mode 100644 index 0000000..5fff1c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr69961b.C @@ -0,0 +1,15 @@ +// PR c++/69961 + +struct A { A (int); }; + +template <typename T> +void foo () +{ + A::A ((T)0); // { dg-error "cannot call constructor .A::A. directly" } +} + +void +bar () +{ + foo<int> (); +} -- 2.8.0.rc0.11.g9bfbc33