diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-02-20 03:19:35 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-02-20 03:19:35 +0000 |
commit | 34b41d939a1328f484511c6002ba2456db879a29 (patch) | |
tree | 9631c2ce7dde0b9c680fe463d5718d0cb8f92e45 /lib/Sema/SemaTemplateDeduction.cpp | |
parent | 9ed9a250180f19b2c44df83a196fc3a2ac82f817 (diff) |
Implement the C++0x deduced 'auto' feature.
This fixes PR 8738, 9060 and 9132.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126069 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateDeduction.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 106 |
1 files changed, 101 insertions, 5 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index fceeaa7fdd..bd0a618283 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -22,6 +22,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "llvm/ADT/BitVector.h" +#include "TreeTransform.h" #include <algorithm> namespace clang { @@ -2445,21 +2446,22 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, ParamType = ParamType.getLocalUnqualifiedType(); const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>(); if (ParamRefType) { + QualType PointeeType = ParamRefType->getPointeeType(); + // [C++0x] If P is an rvalue reference to a cv-unqualified // template parameter and the argument is an lvalue, the type // "lvalue reference to A" is used in place of A for type // deduction. - if (const RValueReferenceType *RValueRef - = dyn_cast<RValueReferenceType>(ParamType)) { - if (!RValueRef->getPointeeType().getQualifiers() && - isa<TemplateTypeParmType>(RValueRef->getPointeeType()) && + if (isa<RValueReferenceType>(ParamType)) { + if (!PointeeType.getQualifiers() && + isa<TemplateTypeParmType>(PointeeType) && Arg->Classify(S.Context).isLValue()) ArgType = S.Context.getLValueReferenceType(ArgType); } // [...] If P is a reference type, the type referred to by P is used // for type deduction. - ParamType = ParamRefType->getPointeeType(); + ParamType = PointeeType; } // Overload sets usually make this parameter an undeduced @@ -2946,6 +2948,95 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType(), Specialization, Info); } +namespace { + /// Substitute the 'auto' type specifier within a type for a given replacement + /// type. + class SubstituteAutoTransform : + public TreeTransform<SubstituteAutoTransform> { + QualType Replacement; + public: + SubstituteAutoTransform(Sema &SemaRef, QualType Replacement) : + TreeTransform<SubstituteAutoTransform>(SemaRef), Replacement(Replacement) { + } + QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) { + // If we're building the type pattern to deduce against, don't wrap the + // substituted type in an AutoType. Certain template deduction rules + // apply only when a template type parameter appears directly (and not if + // the parameter is found through desugaring). For instance: + // auto &&lref = lvalue; + // must transform into "rvalue reference to T" not "rvalue reference to + // auto type deduced as T" in order for [temp.deduct.call]p3 to apply. + if (isa<TemplateTypeParmType>(Replacement)) { + QualType Result = Replacement; + TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } else { + QualType Result = RebuildAutoType(Replacement); + AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } + } + }; +} + +/// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6) +/// +/// \param Type the type pattern using the auto type-specifier. +/// +/// \param Init the initializer for the variable whose type is to be deduced. +/// +/// \param Result if type deduction was successful, this will be set to the +/// deduced type. This may still contain undeduced autos if the type is +/// dependent. +/// +/// \returns true if deduction succeeded, false if it failed. +bool +Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) { + if (Init->isTypeDependent()) { + Result = Type; + return true; + } + + SourceLocation Loc = Init->getExprLoc(); + + LocalInstantiationScope InstScope(*this); + + // Build template<class TemplParam> void Func(FuncParam); + NamedDecl *TemplParam + = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false); + TemplateParameterList *TemplateParams + = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc); + + QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false); + QualType FuncParam = + SubstituteAutoTransform(*this, TemplArg).TransformType(Type); + + // Deduce type of TemplParam in Func(Init) + llvm::SmallVector<DeducedTemplateArgument, 1> Deduced; + Deduced.resize(1); + QualType InitType = Init->getType(); + unsigned TDF = 0; + if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams, + FuncParam, InitType, Init, + TDF)) + return false; + + TemplateDeductionInfo Info(Context, Loc); + if (::DeduceTemplateArguments(*this, TemplateParams, + FuncParam, InitType, Info, Deduced, + TDF)) + return false; + + QualType DeducedType = Deduced[0].getAsType(); + if (DeducedType.isNull()) + return false; + + Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type); + return true; +} + static void MarkUsedTemplateParameters(Sema &SemaRef, QualType T, bool OnlyDeduced, @@ -3740,6 +3831,11 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, OnlyDeduced, Depth, Used); break; + case Type::Auto: + MarkUsedTemplateParameters(SemaRef, + cast<AutoType>(T)->getDeducedType(), + OnlyDeduced, Depth, Used); + // None of these types have any template parameters in them. case Type::Builtin: case Type::VariableArray: |