[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