[cfe-commits] [PATCH] Implement C++0x deduced auto type
Douglas Gregor
dgregor at apple.com
Mon Feb 21 09:42:52 PST 2011
On Feb 20, 2011, at 3:57 PM, Richard Smith wrote:
> Hi,
>
> The attached patch makes the remaining requested tweaks:
Looks good, please go ahead and commit!
- Doug
> On Fri, February 18, 2011 17:52, Douglas Gregor wrote:
>> On Feb 17, 2011, at 6:26 PM, Richard Smith wrote:
>>> The attached patch implements the C++0x deduced 'auto' type feature.
>>> This
>>> should fix the following PRs:
>>>
>>> Bug 8738 - C++'0x auto not implemented
>>> Bug 9060 - Late-specified return type accepted for parenthesized
>>> declarator Bug 9132 - clang accepts declarators other than a literal
>>> 'auto' as the
>>> return type of a function with a trailing-return-type
>
> [snip]
>
>> Index: include/clang/AST/Decl.h
>> ===================================================================
>> --- include/clang/AST/Decl.h (revision 125795)
>> +++ include/clang/AST/Decl.h (working copy)
>> @@ -646,6 +646,10 @@
>> /// \brief Whether this local variable could be allocated in the return
>> /// slot of its function, enabling the named return value optimization
>> (NRVO).
>> bool NRVOVariable : 1; +
>> + /// \brief Whether this variable has a deduced C++0x auto type for
>> which we're + /// currently parsing the initializer.
>> + bool ParsingAutoInit : 1;
>>
>>
>> It's unfortunate that this temporary bit has to live forever in the AST.
>> Did you consider an alternative, such as a SmallPtrSet inside Sema that
>> tracks the (few, relatively rare) VarDecls that are waiting for their
>> initializers? (I guess in the future, FieldDecls must also be
>> considered).
>
> Done. I've rearranged the point where the flag is cleared to be sure we
> cover all the cases, and added an assert in case any are missed. I've
> added Sema::FinalizeDeclarator function to be called once a declaration is
> complete (with any initializer attached) which removes the flag.
>
>> +/// \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;
>> +}
>> +
>>
>>
>> 1-1 mapping between standard and implementation, I like it! I do wonder
>> if we could reduce the memory footprint a bit by, e.g., allocating the
>> template parameter list and template type parameter on the stack rather
>> than in the never-to-be-freed ASTContext.
>
> Done. I've added a FixedSizeTemplateParameterList class template to
> implement the variable-sized array suffix for TemplateParameterList.
>
>> Index: lib/AST/ItaniumMangle.cpp
>> ===================================================================
>> --- lib/AST/ItaniumMangle.cpp (revision 125795)
>> +++ lib/AST/ItaniumMangle.cpp (working copy)
>> @@ -1313,9 +1313,6 @@
>> assert(false && "Overloaded and dependent types shouldn't get to name
>> mangling"); break; - case BuiltinType::UndeducedAuto:
>> - assert(0 && "Should not see undeduced auto here");
>> - break;
>> case BuiltinType::ObjCId: Out << "11objc_object"; break; case
>> BuiltinType::ObjCClass: Out << "10objc_class"; break;
>> case BuiltinType::ObjCSel: Out << "13objc_selector"; break; @@ -1648,6
>> +1645,12 @@
>> Out << 'E';
>> }
>>
>>
>> +void CXXNameMangler::mangleType(const AutoType *T) {
>> + QualType D = T->getDeducedType();
>> + assert(!D.isNull() && "can't mangle undeduced auto type");
>> + mangleType(D);
>> +}
>>
>>
>> Please make this an error (via the Diagnostics subsystem) rather than an
>> assertion... I can think of evil ways to write code that would trip up
>> here, which we should (but don't) diagnose as errors. I'd rather fail
>> gracefully.
>
> Done. I managed to tickle this with:
>
> template<typename T> void f(decltype(new auto(T())));
> template void f<int>(int*);
>
>> Index: lib/AST/ASTContext.cpp
>> ===================================================================
>> --- lib/AST/ASTContext.cpp (revision 125795)
>> +++ lib/AST/ASTContext.cpp (working copy)
>> @@ -2674,6 +2677,14 @@
>> return QualType(dt, 0); }
>>
>>
>> +/// getAutoType - Unlike many "get<Type>" functions, we don't unique
>> +/// AutoType AST's.
>> +QualType ASTContext::getAutoType(QualType DeducedType) const {
>> + AutoType *at = new (*this, TypeAlignment) AutoType(DeducedType);
>> + Types.push_back(at);
>> + return QualType(at, 0);
>> +}
>>
>>
>> Why not unique 'auto' types when we have a deduced type?
>
> Done.
>
> Thanks,
> Richard<clang-auto-tweaks.diff>
More information about the cfe-commits
mailing list