зеркало из https://github.com/microsoft/clang-1.git
Fix PR9488: 'auto' type substitution can fail (for instance, if it creates a reference-to-void type). Don't crash if it does.
Also fix an issue where type source information for the resulting type was being lost. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127811 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
827bbcc8a9
Коммит
a085da8624
|
@ -3879,7 +3879,8 @@ public:
|
||||||
FunctionDecl *&Specialization,
|
FunctionDecl *&Specialization,
|
||||||
sema::TemplateDeductionInfo &Info);
|
sema::TemplateDeductionInfo &Info);
|
||||||
|
|
||||||
bool DeduceAutoType(QualType AutoType, Expr *Initializer, QualType &Result);
|
bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *Initializer,
|
||||||
|
TypeSourceInfo *&Result);
|
||||||
|
|
||||||
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
|
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
|
||||||
FunctionTemplateDecl *FT2,
|
FunctionTemplateDecl *FT2,
|
||||||
|
|
|
@ -4664,15 +4664,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
||||||
|
|
||||||
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
// C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
||||||
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
|
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
|
||||||
QualType DeducedType;
|
TypeSourceInfo *DeducedType = 0;
|
||||||
if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
|
if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
|
||||||
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
|
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
|
||||||
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
|
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
|
||||||
<< Init->getSourceRange();
|
<< Init->getSourceRange();
|
||||||
|
if (!DeducedType) {
|
||||||
RealDecl->setInvalidDecl();
|
RealDecl->setInvalidDecl();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VDecl->setType(DeducedType);
|
VDecl->setTypeSourceInfo(DeducedType);
|
||||||
|
VDecl->setType(DeducedType->getType());
|
||||||
|
|
||||||
// If this is a redeclaration, check that the type we just deduced matches
|
// If this is a redeclaration, check that the type we just deduced matches
|
||||||
// the previously declared type.
|
// the previously declared type.
|
||||||
|
|
|
@ -6137,15 +6137,17 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr *Init = Exprs.get()[0];
|
Expr *Init = Exprs.get()[0];
|
||||||
QualType DeducedType;
|
TypeSourceInfo *DeducedType = 0;
|
||||||
if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
|
if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
|
||||||
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
|
Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
|
||||||
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
|
<< VDecl->getDeclName() << VDecl->getType() << Init->getType()
|
||||||
<< Init->getSourceRange();
|
<< Init->getSourceRange();
|
||||||
|
if (!DeducedType) {
|
||||||
RealDecl->setInvalidDecl();
|
RealDecl->setInvalidDecl();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
VDecl->setType(DeducedType);
|
VDecl->setTypeSourceInfo(DeducedType);
|
||||||
|
VDecl->setType(DeducedType->getType());
|
||||||
|
|
||||||
// If this is a redeclaration, check that the type we just deduced matches
|
// If this is a redeclaration, check that the type we just deduced matches
|
||||||
// the previously declared type.
|
// the previously declared type.
|
||||||
|
|
|
@ -848,16 +848,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
||||||
diag::err_auto_new_ctor_multiple_expressions)
|
diag::err_auto_new_ctor_multiple_expressions)
|
||||||
<< AllocType << TypeRange);
|
<< AllocType << TypeRange);
|
||||||
}
|
}
|
||||||
QualType DeducedType;
|
TypeSourceInfo *DeducedType = 0;
|
||||||
if (!DeduceAutoType(AllocType, ConstructorArgs.get()[0], DeducedType))
|
if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType))
|
||||||
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
|
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
|
||||||
<< AllocType
|
<< AllocType
|
||||||
<< ConstructorArgs.get()[0]->getType()
|
<< ConstructorArgs.get()[0]->getType()
|
||||||
<< TypeRange
|
<< TypeRange
|
||||||
<< ConstructorArgs.get()[0]->getSourceRange());
|
<< ConstructorArgs.get()[0]->getSourceRange());
|
||||||
|
if (!DeducedType)
|
||||||
|
return ExprError();
|
||||||
|
|
||||||
AllocType = DeducedType;
|
AllocTypeInfo = DeducedType;
|
||||||
AllocTypeInfo = Context.getTrivialTypeSourceInfo(AllocType, StartLoc);
|
AllocType = AllocTypeInfo->getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per C++0x [expr.new]p5, the type being constructed may be a
|
// Per C++0x [expr.new]p5, the type being constructed may be a
|
||||||
|
|
|
@ -3003,11 +3003,14 @@ namespace {
|
||||||
///
|
///
|
||||||
/// \param Result if type deduction was successful, this will be set to the
|
/// \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
|
/// deduced type. This may still contain undeduced autos if the type is
|
||||||
/// dependent.
|
/// dependent. This will be set to null if deduction succeeded, but auto
|
||||||
|
/// substitution failed; the appropriate diagnostic will already have been
|
||||||
|
/// produced in that case.
|
||||||
///
|
///
|
||||||
/// \returns true if deduction succeeded, false if it failed.
|
/// \returns true if deduction succeeded, false if it failed.
|
||||||
bool
|
bool
|
||||||
Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
|
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init,
|
||||||
|
TypeSourceInfo *&Result) {
|
||||||
if (Init->isTypeDependent()) {
|
if (Init->isTypeDependent()) {
|
||||||
Result = Type;
|
Result = Type;
|
||||||
return true;
|
return true;
|
||||||
|
@ -3025,8 +3028,10 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
|
||||||
FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
|
FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
|
||||||
Loc);
|
Loc);
|
||||||
|
|
||||||
QualType FuncParam =
|
TypeSourceInfo *FuncParamInfo =
|
||||||
SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
|
SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
|
||||||
|
assert(FuncParamInfo && "substituting template parameter for 'auto' failed");
|
||||||
|
QualType FuncParam = FuncParamInfo->getType();
|
||||||
|
|
||||||
// Deduce type of TemplParam in Func(Init)
|
// Deduce type of TemplParam in Func(Init)
|
||||||
llvm::SmallVector<DeducedTemplateArgument, 1> Deduced;
|
llvm::SmallVector<DeducedTemplateArgument, 1> Deduced;
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
|
||||||
|
|
||||||
|
void f() {
|
||||||
|
auto a = f(); // expected-error {{variable has incomplete type 'void'}}
|
||||||
|
auto &b = f(); // expected-error {{cannot form a reference to 'void'}}
|
||||||
|
auto *c = f(); // expected-error {{incompatible initializer of type 'void'}}
|
||||||
|
|
||||||
|
auto d(f()); // expected-error {{variable has incomplete type 'void'}}
|
||||||
|
auto &&e(f()); // expected-error {{cannot form a reference to 'void'}}
|
||||||
|
auto *g(f()); // expected-error {{incompatible initializer of type 'void'}}
|
||||||
|
|
||||||
|
(void)new auto(f()); // expected-error {{allocation of incomplete type 'void'}}
|
||||||
|
(void)new auto&(f()); // expected-error {{cannot form a reference to 'void'}}
|
||||||
|
(void)new auto*(f()); // expected-error {{incompatible constructor argument of type 'void'}}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче