[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