[cfe-commits] r133237 - /cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Douglas Gregor dgregor at apple.com
Thu Jun 16 22:18:17 PDT 2011


Author: dgregor
Date: Fri Jun 17 00:18:17 2011
New Revision: 133237

URL: http://llvm.org/viewvc/llvm-project?rev=133237&view=rev
Log:
Factor the checking of the deduced argument type against the actual
argument type for C++ [temp.deduct.call]p4 out of
Sema::FinishTemplateArgumentDeduction(). No functionality change.


Modified:
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=133237&r1=133236&r2=133237&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Jun 17 00:18:17 2011
@@ -2314,6 +2314,88 @@
   return TDK_Success;
 }
 
+/// \brief Check whether the deduced argument type for a call to a function
+/// template matches the actual argument type per C++ [temp.deduct.call]p4.
+static bool 
+CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, 
+                              QualType DeducedA) {
+  ASTContext &Context = S.Context;
+  
+  QualType A = OriginalArg.OriginalArgType;
+  QualType OriginalParamType = OriginalArg.OriginalParamType;
+  
+  // Check for type equality (top-level cv-qualifiers are ignored).
+  if (Context.hasSameUnqualifiedType(A, DeducedA))
+    return false;
+  
+  // Strip off references on the argument types; they aren't needed for
+  // the following checks.
+  if (const ReferenceType *DeducedARef = DeducedA->getAs<ReferenceType>())
+    DeducedA = DeducedARef->getPointeeType();
+  if (const ReferenceType *ARef = A->getAs<ReferenceType>())
+    A = ARef->getPointeeType();
+  
+  // C++ [temp.deduct.call]p4:
+  //   [...] However, there are three cases that allow a difference:
+  //     - If the original P is a reference type, the deduced A (i.e., the 
+  //       type referred to by the reference) can be more cv-qualified than 
+  //       the transformed A.
+  if (const ReferenceType *OriginalParamRef
+      = OriginalParamType->getAs<ReferenceType>()) {
+    // We don't want to keep the reference around any more.
+    OriginalParamType = OriginalParamRef->getPointeeType();
+    
+    Qualifiers AQuals = A.getQualifiers();
+    Qualifiers DeducedAQuals = DeducedA.getQualifiers();
+    if (AQuals == DeducedAQuals) {
+      // Qualifiers match; there's nothing to do.
+    } else if (!DeducedAQuals.compatiblyIncludes(AQuals)) {
+      return Sema::TDK_SubstitutionFailure;
+    } else {        
+      // Qualifiers are compatible, so have the argument type adopt the
+      // deduced argument type's qualifiers as if we had performed the
+      // qualification conversion.
+      A = Context.getQualifiedType(A.getUnqualifiedType(), DeducedAQuals);
+    }
+  }
+  
+  //    - The transformed A can be another pointer or pointer to member 
+  //      type that can be converted to the deduced A via a qualification 
+  //      conversion.
+  bool ObjCLifetimeConversion = false;
+  if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
+      S.IsQualificationConversion(A, DeducedA, false, ObjCLifetimeConversion))
+    return false;
+  
+  
+  //    - If P is a class and P has the form simple-template-id, then the 
+  //      transformed A can be a derived class of the deduced A. [...]
+  //     [...] Likewise, if P is a pointer to a class of the form 
+  //      simple-template-id, the transformed A can be a pointer to a 
+  //      derived class pointed to by the deduced A.
+  if (const PointerType *OriginalParamPtr
+      = OriginalParamType->getAs<PointerType>()) {
+    if (const PointerType *DeducedAPtr = DeducedA->getAs<PointerType>()) {
+      if (const PointerType *APtr = A->getAs<PointerType>()) {
+        if (A->getPointeeType()->isRecordType()) {
+          OriginalParamType = OriginalParamPtr->getPointeeType();
+          DeducedA = DeducedAPtr->getPointeeType();
+          A = APtr->getPointeeType();
+        }
+      }
+    }
+  }
+  
+  if (Context.hasSameUnqualifiedType(A, DeducedA))
+    return false;
+  
+  if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
+      S.IsDerivedFrom(A, DeducedA))
+    return false;
+  
+  return true;
+}
+
 /// \brief Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template specialization.
@@ -2487,85 +2569,14 @@
     //   is transformed as described above). [...]
     for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) {
       OriginalCallArg OriginalArg = (*OriginalCallArgs)[I];
-      QualType A = OriginalArg.OriginalArgType;
       unsigned ParamIdx = OriginalArg.ArgIdx;
       
       if (ParamIdx >= Specialization->getNumParams())
         continue;
       
       QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
-      QualType OriginalParamType = OriginalArg.OriginalParamType;
-      
-      // Check for type equality (top-level cv-qualifiers are ignored).
-      if (Context.hasSameUnqualifiedType(A, DeducedA))
-        continue;
-      
-      // Strip off references on the argument types; they aren't needed for
-      // the following checks.
-      if (const ReferenceType *DeducedARef = DeducedA->getAs<ReferenceType>())
-        DeducedA = DeducedARef->getPointeeType();
-      if (const ReferenceType *ARef = A->getAs<ReferenceType>())
-        A = ARef->getPointeeType();
-          
-      // C++ [temp.deduct.call]p4:
-      //   [...] However, there are three cases that allow a difference:
-      //     - If the original P is a reference type, the deduced A (i.e., the 
-      //       type referred to by the reference) can be more cv-qualified than 
-      //       the transformed A.
-      if (const ReferenceType *OriginalParamRef
-                                  = OriginalParamType->getAs<ReferenceType>()) {
-        // We don't want to keep the reference around any more.
-        OriginalParamType = OriginalParamRef->getPointeeType();
-        
-        Qualifiers AQuals = A.getQualifiers();
-        Qualifiers DeducedAQuals = DeducedA.getQualifiers();
-        if (AQuals == DeducedAQuals) {
-          // Qualifiers match; there's nothing to do.
-        } else if (!DeducedAQuals.compatiblyIncludes(AQuals)) {
-          return Sema::TDK_SubstitutionFailure;
-        } else {        
-          // Qualifiers are compatible, so have the argument type adopt the
-          // deduced argument type's qualifiers as if we had performed the
-          // qualification conversion.
-          A = Context.getQualifiedType(A.getUnqualifiedType(), DeducedAQuals);
-        }
-      }
-      
-      //    - The transformed A can be another pointer or pointer to member 
-      //      type that can be converted to the deduced A via a qualification 
-      //      conversion.
-      bool ObjCLifetimeConversion = false;
-      if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
-          IsQualificationConversion(A, DeducedA, false, ObjCLifetimeConversion))
-        continue;
-      
-      
-      //    - If P is a class and P has the form simple-template-id, then the 
-      //      transformed A can be a derived class of the deduced A. [...]
-      //     [...] Likewise, if P is a pointer to a class of the form 
-      //      simple-template-id, the transformed A can be a pointer to a 
-      //      derived class pointed to by the deduced A.
-      if (const PointerType *OriginalParamPtr
-                                    = OriginalParamType->getAs<PointerType>()) {
-        if (const PointerType *DeducedAPtr = DeducedA->getAs<PointerType>()) {
-          if (const PointerType *APtr = A->getAs<PointerType>()) {
-            if (A->getPointeeType()->isRecordType()) {
-              OriginalParamType = OriginalParamPtr->getPointeeType();
-              DeducedA = DeducedAPtr->getPointeeType();
-              A = APtr->getPointeeType();
-            }
-          }
-        }
-      }
-
-      if (Context.hasSameUnqualifiedType(A, DeducedA))
-        continue;
-
-      if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
-          IsDerivedFrom(A, DeducedA))
-        continue;
-
-      return Sema::TDK_SubstitutionFailure;
+      if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA))
+        return Sema::TDK_SubstitutionFailure;
     }
   }
   





More information about the cfe-commits mailing list