diff mbox

C++ PATCH for c++/64455 (dependent variable template in constant expression)

Message ID 54AC5B4F.9080205@redhat.com
State New
Headers show

Commit Message

Jason Merrill Jan. 6, 2015, 10:01 p.m. UTC
We were complaining about IsType<T> not being constant, but we shouldn't 
think about it having a constant value or not, because it is 
type-dependent; a variable template can have a specialization with a 
different type.

Tested x86_64-pc-linux-gnu, applying to trunk.

Comments

Jason Merrill Jan. 6, 2015, 10:02 p.m. UTC | #1
On 01/06/2015 05:01 PM, Jason Merrill wrote:
> We were complaining about IsType<T> not being constant, but we shouldn't
> think about it having a constant value or not, because it is
> type-dependent; a variable template can have a specialization with a
> different type.

The second patch fixes a diagnostic issue I noticed while working on the 
above patch: we should say something helpful when someone writes :: 
after a variable template-id.

Jason
diff mbox

Patch

commit dff5042c89e83955238c9ec5b43a73fa2d2f3310
Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Jan 6 20:44:51 2015 +0000

    	PR c++/64455
    	* pt.c (type_dependent_expression_p): Handle variable templates.
    	* constexpr.c (potential_constant_expression_1): Use it.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219268 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index ee796df..4da263e 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3882,7 +3882,7 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict,
 	      || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t))
 	      || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))
 	  && !var_in_constexpr_fn (t)
-	  && !dependent_type_p (TREE_TYPE (t)))
+	  && !type_dependent_expression_p (t))
         {
           if (flags & tf_error)
             non_const_var_error (t);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 15645b9..de2f6a4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21369,6 +21369,14 @@  type_dependent_expression_p (tree expression)
       && DECL_INITIAL (expression))
    return true;
 
+  /* A variable template specialization is type-dependent if it has any
+     dependent template arguments.  */
+  if (VAR_P (expression)
+      && DECL_LANG_SPECIFIC (expression)
+      && DECL_TEMPLATE_INFO (expression)
+      && variable_template_p (DECL_TI_TEMPLATE (expression)))
+    return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
+
   if (TREE_TYPE (expression) == unknown_type_node)
     {
       if (TREE_CODE (expression) == ADDR_EXPR)
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ21.C b/gcc/testsuite/g++.dg/cpp1y/var-templ21.C
new file mode 100644
index 0000000..a7b0899
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ21.C
@@ -0,0 +1,25 @@ 
+// PR c++/64455
+// { dg-do compile { target c++14 } }
+
+template<typename Type>
+constexpr bool IsType = true;
+
+template <bool b, class T> struct Test
+{
+};
+
+template <class T>
+struct Test<true, T>
+{
+        typedef T type;
+};
+
+template<class T>
+struct X {
+    typedef typename Test<IsType<T>,T>::type type;
+};
+
+int main()
+{
+   X<int>::type t;
+}

commit 33dba2339488931a8630a2414be1d9d4604370e8
Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Jan 6 20:44:59 2015 +0000

    	* parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid
    	template-ids.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219269 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 22dff06..5c23a36 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5435,6 +5435,46 @@  cp_parser_nested_name_specifier_opt (cp_parser *parser,
 	      cp_lexer_consume_token (parser->lexer);
 	    }
 
+	  if (cp_lexer_next_token_is (parser->lexer, CPP_TEMPLATE_ID)
+	      && cp_lexer_nth_token_is (parser->lexer, 2, CPP_SCOPE))
+	    {
+	      /* If we have a non-type template-id followed by ::, it can't
+		 possibly be valid.  */
+	      token = cp_lexer_peek_token (parser->lexer);
+	      tree tid = token->u.tree_check_value->value;
+	      if (TREE_CODE (tid) == TEMPLATE_ID_EXPR
+		  && TREE_CODE (TREE_OPERAND (tid, 0)) != IDENTIFIER_NODE)
+		{
+		  tree tmpl = NULL_TREE;
+		  if (is_overloaded_fn (tid))
+		    {
+		      tree fns = get_fns (tid);
+		      if (!OVL_CHAIN (fns))
+			tmpl = OVL_CURRENT (fns);
+		      error_at (token->location, "function template-id %qD "
+				"in nested-name-specifier", tid);
+		    }
+		  else
+		    {
+		      /* Variable template.  */
+		      tmpl = TREE_OPERAND (tid, 0);
+		      gcc_assert (variable_template_p (tmpl));
+		      error_at (token->location, "variable template-id %qD "
+				"in nested-name-specifier", tid);
+		    }
+		  if (tmpl)
+		    inform (DECL_SOURCE_LOCATION (tmpl),
+			    "%qD declared here", tmpl);
+
+		  parser->scope = error_mark_node;
+		  error_p = true;
+		  /* As below.  */
+		  success = true;
+		  cp_lexer_consume_token (parser->lexer);
+		  cp_lexer_consume_token (parser->lexer);
+		}
+	    }
+
 	  if (cp_parser_uncommitted_to_tentative_parse_p (parser))
 	    break;
 	  /* If the next token is an identifier, and the one after
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ20.C b/gcc/testsuite/g++.dg/cpp1y/var-templ20.C
new file mode 100644
index 0000000..38bd370
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ20.C
@@ -0,0 +1,12 @@ 
+// { dg-do compile { target c++14 } }
+
+template <bool> struct Sink {};
+template <class T> void fn();
+template <class T> T var = T();
+
+template <class T> void f()
+{
+  Sink<fn<T>::value>();		// { dg-error "function" }
+  Sink<var<T>::value>();	// { dg-error "variable" }
+}
+// { dg-prune-output "template argument" }