forked from OSchip/llvm-project
PR31846: Don't replace 'auto' type with a template parameter type in a generic lambda
until after we've checked whether 'auto' is valid in the current language mode. llvm-svn: 294078
This commit is contained in:
parent
56ca3a9ad9
commit
33c33c3e86
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue