This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 28211


This patch fixes a diagnostic regression.  For: 

  S<&v>

if v did not have external linkage, we gave a relatively cryptic error
message:

testcase.cc:4: error: missing '>' to terminate the template argument list
testcase.cc:4: error: template argument 1 is invalid

For "v" alone, if "v" does not have external linkage we cannot give an
error message, as "v" might be a constant-expression (e.g., "const int
v = 7").  But, "&v" is never a constant-expression, so we can accept
it as a valid non-type argument in the parser, and then issue an error
later, during semantic processing.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.  I don't
think there's enough bang-for-risk to backport this to older branches.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2006-10-16  Mark Mitchell  <mark@codesourcery.com>

	PR c++/28211
	* parser.c (cp_parser_template_argument): Don't consider "&var" a
	possible constant-expression.
	* pt.c (convert_nontype_argument): Refine handling of arguments of
	pointer type.

2006-10-16  Mark Mitchell  <mark@codesourcery.com>

	PR c++/28211
	* g++.dg/tc1/dr49.C: Tweak error messages.
	* g++.dg/parse/template21.C: New test.

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 117657)
+++ gcc/cp/pt.c	(working copy)
@@ -3655,10 +3655,46 @@ convert_nontype_argument (tree type, tre
 
 	Here, we do not care about functions, as they are invalid anyway
 	for a parameter of type pointer-to-object.  */
-      bool constant_address_p =
-	(TREE_CODE (expr) == ADDR_EXPR
-	 || TREE_CODE (expr_type) == ARRAY_TYPE
-	 || (DECL_P (expr) && DECL_TEMPLATE_PARM_P (expr)));
+
+      if (DECL_P (expr) && DECL_TEMPLATE_PARM_P (expr))
+	/* Non-type template parameters are OK.  */
+	;
+      else if (TREE_CODE (expr) != ADDR_EXPR
+	       && TREE_CODE (expr_type) != ARRAY_TYPE)
+	{
+	  if (TREE_CODE (expr) == VAR_DECL)
+	    {
+	      error ("%qD is not a valid template argument "
+		     "because %qD is a variable, not the address of "
+		     "a variable",
+		     expr, expr);
+	      return NULL_TREE;
+	    }
+	  /* Other values, like integer constants, might be valid
+	     non-type arguments of some other type.  */
+	  return error_mark_node;
+	}
+      else
+	{
+	  tree decl;
+
+	  decl = ((TREE_CODE (expr) == ADDR_EXPR)
+		  ? TREE_OPERAND (expr, 0) : expr);
+	  if (TREE_CODE (decl) != VAR_DECL)
+	    {
+	      error ("%qE is not a valid template argument of type %qT "
+		     "because %qE is not a variable",
+		     expr, type, decl);
+	      return NULL_TREE;
+	    }
+	  else if (!DECL_EXTERNAL_LINKAGE_P (decl))
+	    {
+	      error ("%qE is not a valid template argument of type %qT "
+		     "because %qD does not have external linkage",
+		     expr, type, decl);
+	      return NULL_TREE;
+	    }
+	}
 
       expr = decay_conversion (expr);
       if (expr == error_mark_node)
@@ -3667,13 +3703,6 @@ convert_nontype_argument (tree type, tre
       expr = perform_qualification_conversions (type, expr);
       if (expr == error_mark_node)
 	return error_mark_node;
-
-      if (!constant_address_p)
-	{
-	  error ("%qE is not a valid template argument for type %qT "
-		 "because it is not a constant pointer", expr, type);
-	  return NULL_TREE;
-	}
     }
   /* [temp.arg.nontype]/5, bullet 3
 
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 117687)
+++ gcc/cp/parser.c	(working copy)
@@ -9285,7 +9285,7 @@ cp_parser_template_argument (cp_parser* 
 	      /* A variable without external linkage might still be a
 		 valid constant-expression, so no error is issued here
 		 if the external-linkage check fails.  */
-	      if (!DECL_EXTERNAL_LINKAGE_P (argument))
+	      if (!address_p && !DECL_EXTERNAL_LINKAGE_P (argument))
 		cp_parser_simulate_error (parser);
 	    }
 	  else if (is_overloaded_fn (argument))
Index: gcc/testsuite/g++.dg/tc1/dr49.C
===================================================================
--- gcc/testsuite/g++.dg/tc1/dr49.C	(revision 117657)
+++ gcc/testsuite/g++.dg/tc1/dr49.C	(working copy)
@@ -10,8 +10,8 @@ template struct R<&p>; // OK
 template struct S<&p>; // OK due to parameter adjustment
 
 int *ptr;
-template struct R<ptr>; // { dg-error "constant" }
-template struct S<ptr>; // { dg-error "constant" }
+template struct R<ptr>; // { dg-error "argument" }
+template struct S<ptr>; // { dg-error "argument" }
 
 int v[5];
 template struct R<v>; // OK due to implicit argument conversion
Index: gcc/testsuite/g++.dg/parse/template21.C
===================================================================
--- gcc/testsuite/g++.dg/parse/template21.C	(revision 0)
+++ gcc/testsuite/g++.dg/parse/template21.C	(revision 0)
@@ -0,0 +1,5 @@
+// PR c++/28211
+
+template <const int*> class Helper { };
+const int foo = 0;
+typedef Helper<&foo> HelperType; // { dg-error "linkage|type" }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]