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
|
/// \brief Substitute Replacement for auto in TypeWithAuto
|
||||||
TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
|
TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
|
||||||
QualType Replacement);
|
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.
|
/// \brief Result type of DeduceAutoType.
|
||||||
enum DeduceAutoResult {
|
enum DeduceAutoResult {
|
||||||
|
|
|
@ -4250,6 +4250,13 @@ TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
|
||||||
.TransformType(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) {
|
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
|
||||||
if (isa<InitListExpr>(Init))
|
if (isa<InitListExpr>(Init))
|
||||||
Diag(VDecl->getLocation(),
|
Diag(VDecl->getLocation(),
|
||||||
|
|
|
@ -1502,40 +1502,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeclSpec::TST_auto:
|
case DeclSpec::TST_auto:
|
||||||
// TypeQuals handled by caller.
|
Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DeclSpec::TST_auto_type:
|
case DeclSpec::TST_auto_type:
|
||||||
|
@ -2802,6 +2769,32 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
|
||||||
if (!SemaRef.getLangOpts().CPlusPlus14 ||
|
if (!SemaRef.getLangOpts().CPlusPlus14 ||
|
||||||
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
|
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
|
||||||
Error = 16;
|
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;
|
break;
|
||||||
case Declarator::MemberContext: {
|
case Declarator::MemberContext: {
|
||||||
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
|
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
|
||||||
|
|
|
@ -8,3 +8,10 @@ void f() {
|
||||||
typedef auto PR25449(); // expected-error {{'auto' not allowed in typedef}}
|
typedef auto PR25449(); // expected-error {{'auto' not allowed in typedef}}
|
||||||
|
|
||||||
thread_local auto x; // expected-error {{requires an initializer}}
|
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