Eliminate a 'default' case in template argument deduction, where we
were just punting on template argument deduction for a number of type
nodes. Most of them, obviously, didn't matter.

As a consequence of this, make extended vector types (via the
ext_vector_type attribute) actually work properly for several
important cases:
  - If the attribute appears in a type-id (i.e, not attached to a
  typedef), actually build a proper vector type
  - Build ExtVectorType whenever the size is constant; previously, we
  were building DependentSizedExtVectorType when the size was constant
  but the type was dependent, which makes no sense at all.
  - Teach template argument deduction to handle
  ExtVectorType/DependentSizedExtVectorType.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133060 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1ec7199..430b4f9 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -217,7 +217,12 @@
     CXXScopeSpec SS;
     UnqualifiedId id;
     id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
-    sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
+    
+    ExprResult Size = S.ActOnIdExpression(scope, SS, id, false, false);
+    if (Size.isInvalid())
+      return;
+    
+    sizeExpr = Size.get();
   } else {
     // check the attribute arguments.
     if (Attr.getNumArgs() != 1) {
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 842c5fb..9011cdf 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1053,10 +1053,39 @@
   }
 
   switch (Param->getTypeClass()) {
-    // No deduction possible for these types
+    // Non-canonical types cannot appear here.
+#define NON_CANONICAL_TYPE(Class, Base) \
+  case Type::Class: llvm_unreachable("deducing non-canonical type: " #Class);
+#define TYPE(Class, Base)
+#include "clang/AST/TypeNodes.def"
+      
+    case Type::TemplateTypeParm:
+    case Type::SubstTemplateTypeParmPack:
+      llvm_unreachable("Type nodes handled above");
+      
+    // These types cannot be used in templates or cannot be dependent, so
+    // deduction always fails.
     case Type::Builtin:
+    case Type::VariableArray:
+    case Type::Vector:
+    case Type::FunctionNoProto:
+    case Type::Record:
+    case Type::Enum:
+    case Type::ObjCObject:
+    case Type::ObjCInterface:
+    case Type::ObjCObjectPointer:
       return Sema::TDK_NonDeducedMismatch;
 
+    //     _Complex T   [placeholder extension]  
+    case Type::Complex:
+      if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
+        return DeduceTemplateArguments(S, TemplateParams, 
+                                    cast<ComplexType>(Param)->getElementType(), 
+                                       ComplexArg->getElementType(),
+                                       Info, Deduced, TDF);
+
+      return Sema::TDK_NonDeducedMismatch;
+      
     //     T *
     case Type::Pointer: {
       QualType PointeeType;
@@ -1360,14 +1389,105 @@
                                      Deduced, 0);
     }
 
+    //     (clang extension)
+    //
+    //     T __attribute__(((ext_vector_type(<integral constant>))))
+    case Type::ExtVector: {
+      const ExtVectorType *VectorParam = cast<ExtVectorType>(Param);
+      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+        // Make sure that the vectors have the same number of elements.
+        if (VectorParam->getNumElements() != VectorArg->getNumElements())
+          return Sema::TDK_NonDeducedMismatch;
+        
+        // Perform deduction on the element types.
+        return DeduceTemplateArguments(S, TemplateParams,
+                                       VectorParam->getElementType(),
+                                       VectorArg->getElementType(),
+                                       Info, Deduced,
+                                       TDF);
+      }
+      
+      if (const DependentSizedExtVectorType *VectorArg 
+                                = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+        // We can't check the number of elements, since the argument has a
+        // dependent number of elements. This can only occur during partial
+        // ordering.
+
+        // Perform deduction on the element types.
+        return DeduceTemplateArguments(S, TemplateParams,
+                                       VectorParam->getElementType(),
+                                       VectorArg->getElementType(),
+                                       Info, Deduced,
+                                       TDF);
+      }
+      
+      return Sema::TDK_NonDeducedMismatch;
+    }
+      
+    //     (clang extension)
+    //
+    //     T __attribute__(((ext_vector_type(N))))
+    case Type::DependentSizedExtVector: {
+      const DependentSizedExtVectorType *VectorParam
+        = cast<DependentSizedExtVectorType>(Param);
+
+      if (const ExtVectorType *VectorArg = dyn_cast<ExtVectorType>(Arg)) {
+        // Perform deduction on the element types.
+        if (Sema::TemplateDeductionResult Result
+              = DeduceTemplateArguments(S, TemplateParams,
+                                        VectorParam->getElementType(),
+                                        VectorArg->getElementType(),
+                                        Info, Deduced,
+                                        TDF))
+          return Result;
+        
+        // Perform deduction on the vector size, if we can.
+        NonTypeTemplateParmDecl *NTTP
+          = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+        if (!NTTP)
+          return Sema::TDK_Success;
+
+        llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
+        ArgSize = VectorArg->getNumElements();
+        return DeduceNonTypeTemplateArgument(S, NTTP, ArgSize, S.Context.IntTy,
+                                             false, Info, Deduced);
+      }
+      
+      if (const DependentSizedExtVectorType *VectorArg 
+                                = dyn_cast<DependentSizedExtVectorType>(Arg)) {
+        // Perform deduction on the element types.
+        if (Sema::TemplateDeductionResult Result
+            = DeduceTemplateArguments(S, TemplateParams,
+                                      VectorParam->getElementType(),
+                                      VectorArg->getElementType(),
+                                      Info, Deduced,
+                                      TDF))
+          return Result;
+        
+        // Perform deduction on the vector size, if we can.
+        NonTypeTemplateParmDecl *NTTP
+          = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+        if (!NTTP)
+          return Sema::TDK_Success;
+        
+        return DeduceNonTypeTemplateArgument(S, NTTP, VectorArg->getSizeExpr(),
+                                             Info, Deduced);
+      }
+      
+      return Sema::TDK_NonDeducedMismatch;
+    }
+      
     case Type::TypeOfExpr:
     case Type::TypeOf:
     case Type::DependentName:
+    case Type::UnresolvedUsing:
+    case Type::Decltype:
+    case Type::UnaryTransform:
+    case Type::Auto:
+    case Type::DependentTemplateSpecialization:
+    case Type::PackExpansion:
       // No template argument deduction for these types
       return Sema::TDK_Success;
-
-    default:
-      break;
   }
 
   // FIXME: Many more cases to go (to go).
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index ec8fdc9..ef3c262 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1320,8 +1320,7 @@
       return QualType();
     }
 
-    if (!T->isDependentType())
-      return Context.getExtVectorType(T, vectorSize);
+    return Context.getExtVectorType(T, vectorSize);
   }
 
   return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
@@ -3151,6 +3150,40 @@
                                     VectorType::GenericVector);
 }
 
+/// \brief Process the OpenCL-like ext_vector_type attribute when it occurs on
+/// a type.
+static void HandleExtVectorTypeAttr(QualType &CurType, 
+                                    const AttributeList &Attr, 
+                                    Sema &S) {
+  Expr *sizeExpr;
+  
+  // Special case where the argument is a template id.
+  if (Attr.getParameterName()) {
+    CXXScopeSpec SS;
+    UnqualifiedId id;
+    id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+    
+    ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, id, false, 
+                                          false);
+    if (Size.isInvalid())
+      return;
+    
+    sizeExpr = Size.get();
+  } else {
+    // check the attribute arguments.
+    if (Attr.getNumArgs() != 1) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+      return;
+    }
+    sizeExpr = Attr.getArg(0);
+  }
+  
+  // Create the vector type.
+  QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
+  if (!T.isNull())
+    CurType = T;
+}
+
 /// HandleNeonVectorTypeAttr - The "neon_vector_type" and
 /// "neon_polyvector_type" attributes are used to create vector types that
 /// are mangled according to ARM's ABI.  Otherwise, these types are identical
@@ -3241,6 +3274,11 @@
     case AttributeList::AT_vector_size:
       HandleVectorSizeAttr(type, attr, state.getSema());
       break;
+    case AttributeList::AT_ext_vector_type:
+      if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
+            != DeclSpec::SCS_typedef)
+        HandleExtVectorTypeAttr(type, attr, state.getSema());
+      break;
     case AttributeList::AT_neon_vector_type:
       HandleNeonVectorTypeAttr(type, attr, state.getSema(),
                                VectorType::NeonVector, "neon_vector_type");