[cfe-commits] r74331 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiate.cpp test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp

Douglas Gregor dgregor at apple.com
Fri Jun 26 14:40:13 PDT 2009


Author: dgregor
Date: Fri Jun 26 16:40:05 2009
New Revision: 74331

URL: http://llvm.org/viewvc/llvm-project?rev=74331&view=rev
Log:
A little template argument deduction test uncovered an "oops". As part
of template instantiation, we were dropping cv-qualifiers on the
instantiated type in a few places. This change reshuffles the
type-instantiation code a little bit so that there's a single place
where we add qualifiers to the instantiated type, so that we won't end
up with this same bug in the future.


Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=74331&r1=74330&r2=74331&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jun 26 16:40:05 2009
@@ -262,88 +262,82 @@
 
     // Declare instantiate functions for each type.
 #define TYPE(Class, Base)                                       \
-    QualType Instantiate##Class##Type(const Class##Type *T,     \
-                                      unsigned Quals) const;
+    QualType Instantiate##Class##Type(const Class##Type *T) const;
 #define ABSTRACT_TYPE(Class, Base)
 #include "clang/AST/TypeNodes.def"
   };
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T,
-                                                 unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate ExtQualType yet");
   return QualType();
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T,
-                                                 unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T) const {
   assert(false && "Builtin types are not dependent and cannot be instantiated");
-  return QualType(T, Quals);
+  return QualType(T, 0);
 }
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateFixedWidthIntType(const FixedWidthIntType *T, unsigned Quals) const {
+InstantiateFixedWidthIntType(const FixedWidthIntType *T) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate FixedWidthIntType yet");
   return QualType();
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T,
-                                                 unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate ComplexType yet");
   return QualType();
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T,
-                                                 unsigned Quals) const {
+TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T) const {
   QualType PointeeType = Instantiate(T->getPointeeType());
   if (PointeeType.isNull())
     return QualType();
 
-  return SemaRef.BuildPointerType(PointeeType, Quals, Loc, Entity);
+  return SemaRef.BuildPointerType(PointeeType, 0, Loc, Entity);
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T,
-                                                      unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateBlockPointerType(
+                                            const BlockPointerType *T) const {
   QualType PointeeType = Instantiate(T->getPointeeType());
   if (PointeeType.isNull())
     return QualType();
   
-  return SemaRef.BuildBlockPointerType(PointeeType, Quals, Loc, Entity);
+  return SemaRef.BuildBlockPointerType(PointeeType, 0, Loc, Entity);
 }
 
 QualType
 TemplateTypeInstantiator::InstantiateLValueReferenceType(
-    const LValueReferenceType *T, unsigned Quals) const {
+                                        const LValueReferenceType *T) const {
   QualType ReferentType = Instantiate(T->getPointeeType());
   if (ReferentType.isNull())
     return QualType();
 
-  return SemaRef.BuildReferenceType(ReferentType, true, Quals, Loc, Entity);
+  return SemaRef.BuildReferenceType(ReferentType, true, 0, Loc, Entity);
 }
 
 QualType
 TemplateTypeInstantiator::InstantiateRValueReferenceType(
-    const RValueReferenceType *T, unsigned Quals) const {
+                                        const RValueReferenceType *T) const {
   QualType ReferentType = Instantiate(T->getPointeeType());
   if (ReferentType.isNull())
     return QualType();
 
-  return SemaRef.BuildReferenceType(ReferentType, false, Quals, Loc, Entity);
+  return SemaRef.BuildReferenceType(ReferentType, false, 0, Loc, Entity);
 }
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateMemberPointerType(const MemberPointerType *T,
-                             unsigned Quals) const {
+InstantiateMemberPointerType(const MemberPointerType *T) const {
   QualType PointeeType = Instantiate(T->getPointeeType());
   if (PointeeType.isNull())
     return QualType();
@@ -352,14 +346,13 @@
   if (ClassType.isNull())
     return QualType();
 
-  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Quals, Loc, 
+  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0, Loc, 
                                         Entity);
 }
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateConstantArrayType(const ConstantArrayType *T, 
-                             unsigned Quals) const {
+InstantiateConstantArrayType(const ConstantArrayType *T) const {
   QualType ElementType = Instantiate(T->getElementType());
   if (ElementType.isNull())
     return ElementType;
@@ -394,8 +387,7 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateIncompleteArrayType(const IncompleteArrayType *T,
-                               unsigned Quals) const {
+InstantiateIncompleteArrayType(const IncompleteArrayType *T) const {
   QualType ElementType = Instantiate(T->getElementType());
   if (ElementType.isNull())
     return ElementType;
@@ -407,8 +399,7 @@
 
 QualType
 TemplateTypeInstantiator::
-InstantiateVariableArrayType(const VariableArrayType *T,
-                             unsigned Quals) const {
+InstantiateVariableArrayType(const VariableArrayType *T) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate VariableArrayType yet");
   return QualType();
@@ -416,8 +407,7 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
-                                   unsigned Quals) const {
+InstantiateDependentSizedArrayType(const DependentSizedArrayType *T) const {
   Expr *ArraySize = T->getSizeExpr();
   assert(ArraySize->isValueDependent() && 
          "dependent sized array types must have value dependent size expr");
@@ -444,8 +434,8 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T,
-                                   unsigned Quals) const {
+InstantiateDependentSizedExtVectorType(
+                                const DependentSizedExtVectorType *T) const {
 
   // Instantiate the element type if needed.
   QualType ElementType = T->getElementType();
@@ -473,16 +463,15 @@
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T,
-                                             unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate VectorType yet");
   return QualType();
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T,
-                                                   unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateExtVectorType(
+                                              const ExtVectorType *T) const {
   // FIXME: Implement this
   assert(false && "Cannot instantiate ExtVectorType yet");
   return QualType();
@@ -490,8 +479,7 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateFunctionProtoType(const FunctionProtoType *T,
-                             unsigned Quals) const {
+InstantiateFunctionProtoType(const FunctionProtoType *T) const {
   QualType ResultType = Instantiate(T->getResultType());
   if (ResultType.isNull())
     return ResultType;
@@ -515,15 +503,13 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateFunctionNoProtoType(const FunctionNoProtoType *T,
-                               unsigned Quals) const {
+InstantiateFunctionNoProtoType(const FunctionNoProtoType *T) const {
   assert(false && "Functions without prototypes cannot be dependent.");
   return QualType();
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
-                                                 unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T) const {
   TypedefDecl *Typedef 
     = cast_or_null<TypedefDecl>(
                            SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
@@ -534,8 +520,8 @@
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
-                                                    unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateTypeOfExprType(
+                                              const TypeOfExprType *T) const {
   // The expression in a typeof is not potentially evaluated.
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
   
@@ -548,8 +534,7 @@
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T,
-                                                unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T) const {
   QualType Underlying = Instantiate(T->getUnderlyingType());
   if (Underlying.isNull())
     return QualType();
@@ -558,8 +543,7 @@
 }
 
 QualType
-TemplateTypeInstantiator::InstantiateDecltypeType(const DecltypeType *T,
-                                                  unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateDecltypeType(const DecltypeType *T) const {
   // C++0x [dcl.type.simple]p4:
   //   The operand of the decltype specifier is an unevaluated operand.
   EnterExpressionEvaluationContext Unevaluated(SemaRef,
@@ -575,8 +559,7 @@
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
-                                                unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T) const {
   RecordDecl *Record 
     = cast_or_null<RecordDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
   if (!Record)
@@ -586,8 +569,7 @@
 }
 
 QualType 
-TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
-                                              unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T) const {
   EnumDecl *Enum 
     = cast_or_null<EnumDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
   if (!Enum)
@@ -598,26 +580,13 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
-                                unsigned Quals) const {
+InstantiateTemplateTypeParmType(const TemplateTypeParmType *T) const {
   if (T->getDepth() == 0) {
     // Replace the template type parameter with its corresponding
     // template argument.
     assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
            "Template argument kind mismatch");
-    QualType Result = TemplateArgs[T->getIndex()].getAsType();
-    if (Result.isNull() || !Quals) 
-      return Result;
-
-    // C++ [dcl.ref]p1:
-    //   [...] Cv-qualified references are ill-formed except when
-    //   the cv-qualifiers are introduced through the use of a
-    //   typedef (7.1.3) or of a template type argument (14.3), in
-    //   which case the cv-qualifiers are ignored.
-    if (Quals && Result->isReferenceType())
-      Quals = 0;
-
-    return QualType(Result.getTypePtr(), Quals | Result.getCVRQualifiers());
+    return TemplateArgs[T->getIndex()].getAsType();
   } 
 
   // The template type parameter comes from an inner template (e.g.,
@@ -627,15 +596,13 @@
   return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
                                                  T->getIndex(),
                                                  T->isParameterPack(),
-                                                 T->getName())
-    .getQualifiedType(Quals);
+                                                 T->getName());
 }
 
 QualType 
 TemplateTypeInstantiator::
 InstantiateTemplateSpecializationType(
-                                  const TemplateSpecializationType *T,
-                                  unsigned Quals) const {
+                                  const TemplateSpecializationType *T) const {
   llvm::SmallVector<TemplateArgument, 4> InstantiatedTemplateArgs;
   InstantiatedTemplateArgs.reserve(T->getNumArgs());
   for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
@@ -661,8 +628,7 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateQualifiedNameType(const QualifiedNameType *T, 
-                             unsigned Quals) const {
+InstantiateQualifiedNameType(const QualifiedNameType *T) const {
   // When we instantiated a qualified name type, there's no point in
   // keeping the qualification around in the instantiated result. So,
   // just instantiate the named type.
@@ -671,14 +637,14 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateTypenameType(const TypenameType *T, unsigned Quals) const {
+InstantiateTypenameType(const TypenameType *T) const {
   if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
     // When the typename type refers to a template-id, the template-id
     // is dependent and has enough information to instantiate the
     // result of the typename type. Since we don't care about keeping
     // the spelling of the typename type in template instantiations,
     // we just instantiate the template-id.
-    return InstantiateTemplateSpecializationType(TemplateId, Quals);
+    return InstantiateTemplateSpecializationType(TemplateId);
   }
 
   NestedNameSpecifier *NNS 
@@ -693,24 +659,22 @@
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T,
-                                 unsigned Quals) const {
+InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T) const {
   assert(false && "Objective-C types cannot be dependent");
   return QualType();
 }
 
 QualType
 TemplateTypeInstantiator::
-InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
-                             unsigned Quals) const {
+InstantiateObjCInterfaceType(const ObjCInterfaceType *T) const {
   assert(false && "Objective-C types cannot be dependent");
   return QualType();
 }
 
 QualType 
 TemplateTypeInstantiator::
-InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
-                                      unsigned Quals) const {
+InstantiateObjCQualifiedInterfaceType(
+                                 const ObjCQualifiedInterfaceType *T) const {
   assert(false && "Objective-C types cannot be dependent");
   return QualType();
 }
@@ -721,17 +685,27 @@
   if (!T->isDependentType())
     return T;
 
+  QualType Result;
   switch (T->getTypeClass()) {
 #define TYPE(Class, Base)                                               \
   case Type::Class:                                                     \
-    return Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()),  \
-                                    T.getCVRQualifiers());
+    Result = Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()));  \
+    break;
 #define ABSTRACT_TYPE(Class, Base)
 #include "clang/AST/TypeNodes.def"
   }
-  
-  assert(false && "Not all types have been decoded for instantiation");
-  return QualType();
+
+  // C++ [dcl.ref]p1:
+  //   [...] Cv-qualified references are ill-formed except when
+  //   the cv-qualifiers are introduced through the use of a
+  //   typedef (7.1.3) or of a template type argument (14.3), in
+  //   which case the cv-qualifiers are ignored.
+  // 
+  // The same rule applies to function types.
+  if (!Result.isNull() && T.getCVRQualifiers() &&
+      !Result->isFunctionType() && !Result->isReferenceType())
+    Result = Result.getWithAdditionalQualifiers(T.getCVRQualifiers());
+  return Result;
 }
 
 /// \brief Instantiate the type T with a given set of template arguments.

Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp?rev=74331&r1=74330&r2=74331&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp Fri Jun 26 16:40:05 2009
@@ -30,6 +30,13 @@
   B<const int, 3> b1 = g0(array1);
 }
 
+template<typename T> B<T, 0> g1(const A<T>&);
+
+void test_g1(A<float> af) {
+  B<float, 0> b0 = g1(af);
+  B<int, 0> b1 = g1(A<int>());
+}
+
 //   - 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.





More information about the cfe-commits mailing list