Suppress incorrect warning when a keyword is used in template classes

Closes https://github.com/swig/swig/issues/845
diff --git a/CHANGES.current b/CHANGES.current
index aa43877..792bb1b 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -5,6 +5,11 @@
 Version 3.0.11 (in progress)
 ============================
 
+2016-12-20: wsfulton
+            %namewarn unnecessarily caused keyword warnings for non-instantiated template classes
+            and duplicate warnings for instantiated template classes when keywords were used.
+            Issue https://github.com/swig/swig/issues/845
+
 2016-12-18: ezralanglois 
             [Python, Ruby, Octave] Memory leak fix on error in std::pair wrappers.
             Issue https://github.com/swig/swig/pull/851
diff --git a/Examples/test-suite/errors/cpp_namewarn.i b/Examples/test-suite/errors/cpp_namewarn.i
new file mode 100644
index 0000000..c0edc4b
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_namewarn.i
@@ -0,0 +1,80 @@
+%module xxx
+
+%namewarn("314:'key1' is a keyword, renaming to '_key1'", rename="_%s") "key1";
+%namewarn("314:'key2' is a keyword, renaming to '_key2'", rename="_%s") "key2";
+%namewarn("314:'key3' is a keyword, renaming to '_key3'", rename="_%s") "key3";
+%namewarn("314:'key4' is a keyword, renaming to '_key4'", rename="_%s") "key4";
+%namewarn("314:'key5' is a keyword, renaming to '_key5'", rename="_%s") "key5";
+
+// Non-templated
+%ignore KlassA::key1;
+%rename(key2renamed) KlassA::key2;
+%rename(key3renamed) KlassA::key3;
+%rename(key4renamed) KlassA::key4;
+
+// Templated
+%ignore KlassB::key1;
+%rename(key2renamed) KlassB::key2;
+%rename(key3renamed) KlassB<double>::key3;
+
+// Template specialized
+%ignore KlassC::key1;
+%rename(key2renamed) KlassC::key2;
+%rename(key3renamed) KlassC<double>::key3;
+
+// No warnings for these...
+%inline %{
+struct KlassA {
+    void key1() {}
+    void key2() {}
+    void key3() {}
+    template<typename X> void key4(X x) {}
+};
+
+template<class T> struct KlassB {
+    void key1() {}
+    void key2() {}
+    void key3() {}
+};
+
+template<class T> struct KlassC {};
+template<> struct KlassC<double> {
+    void key1() {}
+    void key2() {}
+    void key3() {}
+};
+
+template<typename T> void key5(T t) {}
+
+%}
+
+%template(KlassBDouble) KlassB<double>;
+%template(KlassCInt) KlassC<double>;
+%template(key5renamed) key5<double>;
+
+// These should create a single warning for each keyword...
+%inline %{
+struct ClassA {
+    void key1() {}
+    void key2() {}
+    void key3() {}
+    template<typename X> void key4(X x) {}
+};
+
+template<class T> struct ClassB {
+    void key1() {}
+    void key2() {}
+    void key3() {}
+};
+
+template<class T> struct ClassC {};
+template<> struct ClassC<double> {
+    void key1() {}
+    void key2() {}
+    void key3() {}
+};
+%}
+
+%template(ClassBDouble) ClassB<double>;
+%template(ClassCInt) ClassC<double>;
+%template(key5) key5<int>;
diff --git a/Examples/test-suite/errors/cpp_namewarn.stderr b/Examples/test-suite/errors/cpp_namewarn.stderr
new file mode 100644
index 0000000..e5b8932
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_namewarn.stderr
@@ -0,0 +1,10 @@
+cpp_namewarn.i:58: Warning 314: 'key1' is a keyword, renaming to '_key1'
+cpp_namewarn.i:59: Warning 314: 'key2' is a keyword, renaming to '_key2'
+cpp_namewarn.i:60: Warning 314: 'key3' is a keyword, renaming to '_key3'
+cpp_namewarn.i:65: Warning 314: 'key1' is a keyword, renaming to '_key1'
+cpp_namewarn.i:66: Warning 314: 'key2' is a keyword, renaming to '_key2'
+cpp_namewarn.i:67: Warning 314: 'key3' is a keyword, renaming to '_key3'
+cpp_namewarn.i:72: Warning 314: 'key1' is a keyword, renaming to '_key1'
+cpp_namewarn.i:73: Warning 314: 'key2' is a keyword, renaming to '_key2'
+cpp_namewarn.i:74: Warning 314: 'key3' is a keyword, renaming to '_key3'
+cpp_namewarn.i:80: Warning 314: 'key5' is a keyword, renaming to '_key5'
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 074f96d..ce4d5b2 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -57,6 +57,7 @@
 static const char *last_cpptype = 0;
 static int      inherit_list = 0;
 static Parm    *template_parameters = 0;
+static int      parsing_template_declaration = 0;
 static int      extendmode   = 0;
 static int      compact_default_args = 0;
 static int      template_reduce = 0;
@@ -262,6 +263,7 @@
 
 
 static String *make_name(Node *n, String *name,SwigType *decl) {
+  String *made_name = 0;
   int destructor = name && (*(Char(name)) == '~');
 
   if (yyrename) {
@@ -275,7 +277,13 @@
   }
 
   if (!name) return 0;
-  return Swig_name_make(n,Namespaceprefix,name,decl,add_oldname);
+
+  if (parsing_template_declaration)
+    SetFlag(n, "parsing_template_declaration");
+  made_name = Swig_name_make(n, Namespaceprefix, name, decl, add_oldname);
+  Delattr(n, "parsing_template_declaration");
+
+  return made_name;
 }
 
 /* Generate an unnamed identifier */
@@ -440,7 +448,10 @@
 	symname = Copy(Getattr(n,"unnamed"));
       }
       if (symname) {
+	if (parsing_template_declaration)
+	  SetFlag(n, "parsing_template_declaration");
 	wrn = Swig_name_warning(n, Namespaceprefix, symname,0);
+	Delattr(n, "parsing_template_declaration");
       }
     } else {
       String *name = Getattr(n,"name");
@@ -453,7 +464,10 @@
       Swig_features_get(Swig_cparse_features(),Namespaceprefix,name,fun,n);
 
       symname = make_name(n, name,fun);
+      if (parsing_template_declaration)
+	SetFlag(n, "parsing_template_declaration");
       wrn = Swig_name_warning(n, Namespaceprefix,symname,fun);
+      Delattr(n, "parsing_template_declaration");
       
       Delete(fdecl);
       Delete(fun);
@@ -3850,9 +3864,10 @@
    ------------------------------------------------------------ */
 
 cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { 
-		   if (currentOuterClass)
-		     Setattr(currentOuterClass, "template_parameters", template_parameters);
+		    if (currentOuterClass)
+		      Setattr(currentOuterClass, "template_parameters", template_parameters);
 		    template_parameters = $3; 
+		    parsing_template_declaration = 1;
 		  } cpp_temp_possible {
 			String *tname = 0;
 			int     error = 0;
@@ -4105,6 +4120,7 @@
 			  template_parameters = Getattr(currentOuterClass, "template_parameters");
 			else
 			  template_parameters = 0;
+			parsing_template_declaration = 0;
                 }
 
 		/* Explicit template instantiation */
diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c
index ea059aa..ce1dbe8 100644
--- a/Source/Swig/naming.c
+++ b/Source/Swig/naming.c
@@ -799,6 +799,8 @@
     need = 0;
   } else if (Getattr(n, "templatetype")) {
     need = 0;
+  } else if (GetFlag(n, "parsing_template_declaration")) {
+    need = 0;
   }
   return need;
 }