[cfe-commits] r141809 - in /cfe/trunk: lib/Sema/SemaTemplateDeduction.cpp test/CXX/temp/temp.decls/temp.mem/p5.cpp test/SemaTemplate/operator-template.cpp test/SemaTemplate/temp_arg_nontype.cpp

Douglas Gregor dgregor at apple.com
Wed Oct 12 13:35:48 PDT 2011


Author: dgregor
Date: Wed Oct 12 15:35:48 2011
New Revision: 141809

URL: http://llvm.org/viewvc/llvm-project?rev=141809&view=rev
Log:
When we determine that a function template specialization produced as
part of template argument deduction is ill-formed, we mark it as
invalid and treat it as a deduction failure. If we happen to find that
specialization again, treat it as a deduction failure rather than
silently building a call to the declaration.

Fixes PR11117, a marvelous bug where deduction failed after creating
an invalid specialization, causing overload resolution to pick a
different candidate. Then we performed a similar overload resolution
later, and happily picked the invalid specialization to
call... resulting in a silent link failure.

Modified:
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp
    cfe/trunk/test/SemaTemplate/operator-template.cpp
    cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=141809&r1=141808&r2=141809&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Oct 12 15:35:48 2011
@@ -2589,7 +2589,7 @@
   Specialization = cast_or_null<FunctionDecl>(
                       SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner,
                          MultiLevelTemplateArgumentList(*DeducedArgumentList)));
-  if (!Specialization)
+  if (!Specialization || Specialization->isInvalidDecl())
     return TDK_SubstitutionFailure;
 
   assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() ==
@@ -2601,6 +2601,14 @@
       !Trap.hasErrorOccurred())
     Info.take();
 
+  // There may have been an error that did not prevent us from constructing a
+  // declaration. Mark the declaration invalid and return with a substitution
+  // failure.
+  if (Trap.hasErrorOccurred()) {
+    Specialization->setInvalidDecl(true);
+    return TDK_SubstitutionFailure;
+  }
+
   if (OriginalCallArgs) {
     // C++ [temp.deduct.call]p4:
     //   In general, the deduction process attempts to find template argument
@@ -2619,14 +2627,6 @@
     }
   }
   
-  // There may have been an error that did not prevent us from constructing a
-  // declaration. Mark the declaration invalid and return with a substitution
-  // failure.
-  if (Trap.hasErrorOccurred()) {
-    Specialization->setInvalidDecl(true);
-    return TDK_SubstitutionFailure;
-  }
-
   // If we suppressed any diagnostics while performing template argument
   // deduction, and if we haven't already instantiated this declaration,
   // keep track of these diagnostics. They'll be emitted if this specialization

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp?rev=141809&r1=141808&r2=141809&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp Wed Oct 12 15:35:48 2011
@@ -63,7 +63,8 @@
   
   template<typename T> operator const T*() const {
     T x = T();
-    return x; // expected-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}}
+    return x; // expected-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}} \
+    // expected-error{{cannot initialize return object of type 'const int *' with an lvalue of type 'int'}}
   }
 };
 
@@ -72,7 +73,7 @@
 template X0::operator float*() const; // expected-error{{explicit instantiation of undefined function template}}
 
 void test_X0(X0 x0, const X0 &x0c) {
-  x0.operator const int*();
+  x0.operator const int*(); // expected-note{{in instantiation of function template specialization}}
   x0.operator float *();
   x0c.operator const char*();
 }

Modified: cfe/trunk/test/SemaTemplate/operator-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/operator-template.cpp?rev=141809&r1=141808&r2=141809&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/operator-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/operator-template.cpp Wed Oct 12 15:35:48 2011
@@ -2,7 +2,8 @@
 
 // Make sure we accept this
 template<class X>struct A{typedef X Y;};
-template<class X>bool operator==(A<X>,typename A<X>::Y);
+template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: failed template argument deduction}}
+
 int a(A<int> x) { return operator==(x,1); }
 
 int a0(A<int> x) { return x == 1; }
@@ -10,7 +11,8 @@
 // FIXME: the location information for the note isn't very good
 template<class X>struct B{typedef X Y;};
 template<class X>bool operator==(B<X>*,typename B<X>::Y); // \
-expected-error{{overloaded 'operator==' must have at least one parameter of class or enumeration type}} \
-expected-note{{in instantiation of function template specialization}}
-int a(B<int> x) { return operator==(&x,1); }
+// expected-error{{overloaded 'operator==' must have at least one parameter of class or enumeration type}} \
+// expected-note{{in instantiation of function template specialization}} \
+// expected-note{{candidate template ignored: substitution failure [with X = int]}}
+int a(B<int> x) { return operator==(&x,1); } // expected-error{{no matching function for call to 'operator=='}}
 

Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=141809&r1=141808&r2=141809&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Wed Oct 12 15:35:48 2011
@@ -170,7 +170,7 @@
 
 namespace PR6723 {
   template<unsigned char C> void f(int (&a)[C]); // expected-note {{candidate template ignored}} \
-  // expected-note{{candidate function [with C = '\x00'] not viable: no known conversion from 'int [512]' to 'int (&)[0]' for 1st argument}}
+  // expected-note{{substitution failure [with C = '\x00']}}
   void g() {
     int arr512[512];
     f(arr512); // expected-error{{no matching function for call}}





More information about the cfe-commits mailing list