diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1645b4d439dcf62136658fdd94d9523129c959d7..dc2947f587e4e73ea061f265886e521e3f129e32 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6727,6 +6727,9 @@ public: /// \brief Substitute Replacement for auto in TypeWithAuto TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, QualType Replacement); + /// \brief Completely replace the \c auto in \p TypeWithAuto by + /// \p Replacement. This does not retain any \c auto type sugar. + QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement); /// \brief Result type of DeduceAutoType. enum DeduceAutoResult { diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 688d6bb8e6873990d6804df4bbd976d20886de79..57957c0728a31a34ab4766a6e29aacaf1db624d0 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -4250,6 +4250,13 @@ TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, .TransformType(TypeWithAuto); } +QualType Sema::ReplaceAutoType(QualType TypeWithAuto, + QualType TypeToReplaceAuto) { + return SubstituteAutoTransform(*this, TypeToReplaceAuto, + /*UseAutoSugar*/ false) + .TransformType(TypeWithAuto); +} + void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) { if (isa<InitListExpr>(Init)) Diag(VDecl->getLocation(), diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 92a2ecc22759e864d1f79427700aafd968898e74..a59511ca77ee7ec791624b0911ad3f9215cefdc5 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1502,40 +1502,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { break; case DeclSpec::TST_auto: - // TypeQuals handled by caller. - // If auto is mentioned in a lambda parameter context, convert it to a - // template parameter type immediately, with the appropriate depth and - // index, and update sema's state (LambdaScopeInfo) for the current lambda - // being analyzed (which tracks the invented type template parameter). - if (declarator.getContext() == Declarator::LambdaExprParameterContext) { - sema::LambdaScopeInfo *LSI = S.getCurLambda(); - assert(LSI && "No LambdaScopeInfo on the stack!"); - const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth; - const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size(); - const bool IsParameterPack = declarator.hasEllipsis(); - - // Turns out we must create the TemplateTypeParmDecl here to - // retrieve the corresponding template parameter type. - TemplateTypeParmDecl *CorrespondingTemplateParam = - TemplateTypeParmDecl::Create(Context, - // Temporarily add to the TranslationUnit DeclContext. When the - // associated TemplateParameterList is attached to a template - // declaration (such as FunctionTemplateDecl), the DeclContext - // for each template parameter gets updated appropriately via - // a call to AdoptTemplateParameterList. - Context.getTranslationUnitDecl(), - /*KeyLoc*/ SourceLocation(), - /*NameLoc*/ declarator.getLocStart(), - TemplateParameterDepth, - AutoParameterPosition, // our template param index - /* Identifier*/ nullptr, false, IsParameterPack); - LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam); - // Replace the 'auto' in the function parameter with this invented - // template type parameter. - Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0); - } else { - Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false); - } + Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false); break; case DeclSpec::TST_auto_type: @@ -2802,6 +2769,32 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, if (!SemaRef.getLangOpts().CPlusPlus14 || !Auto || Auto->getKeyword() != AutoTypeKeyword::Auto) Error = 16; + else { + // If auto is mentioned in a lambda parameter context, convert it to a + // template parameter type. + sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda(); + assert(LSI && "No LambdaScopeInfo on the stack!"); + const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth; + const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size(); + const bool IsParameterPack = D.hasEllipsis(); + + // Create the TemplateTypeParmDecl here to retrieve the corresponding + // template parameter type. Template parameters are temporarily added + // to the TU until the associated TemplateDecl is created. + TemplateTypeParmDecl *CorrespondingTemplateParam = + TemplateTypeParmDecl::Create( + SemaRef.Context, SemaRef.Context.getTranslationUnitDecl(), + /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(), + TemplateParameterDepth, AutoParameterPosition, + /*Identifier*/nullptr, false, IsParameterPack); + LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam); + // Replace the 'auto' in the function parameter with this invented + // template type parameter. + // FIXME: Retain some type sugar to indicate that this was written + // as 'auto'. + T = SemaRef.ReplaceAutoType( + T, QualType(CorrespondingTemplateParam->getTypeForDecl(), 0)); + } break; case Declarator::MemberContext: { if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || diff --git a/test/SemaCXX/auto-cxx0x.cpp b/test/SemaCXX/auto-cxx0x.cpp index c37b1386b3af56cd0db2165a42d61034f04d395c..074a01bb839abd76a540791a8fee530e2255b9ee 100644 --- a/test/SemaCXX/auto-cxx0x.cpp +++ b/test/SemaCXX/auto-cxx0x.cpp @@ -8,3 +8,10 @@ void f() { typedef auto PR25449(); // expected-error {{'auto' not allowed in typedef}} thread_local auto x; // expected-error {{requires an initializer}} + +void g() { + [](auto){}(0); +#if __cplusplus == 201103L + // expected-error@-2 {{'auto' not allowed in lambda parameter}} +#endif +}