forked from OSchip/llvm-project
Minor fixups for auto deduction of initializer lists.
Fix some review comments. Add a test for deduction when std::initializer_list isn't available yet. Fix redundant error messages. This fixes and outstanding FIXME too. llvm-svn: 148735
This commit is contained in:
parent
a8b444b08b
commit
09edce0400
|
@ -4644,8 +4644,15 @@ public:
|
|||
FunctionDecl *&Specialization,
|
||||
sema::TemplateDeductionInfo &Info);
|
||||
|
||||
bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer,
|
||||
TypeSourceInfo *&Result);
|
||||
/// \brief Result type of DeduceAutoType.
|
||||
enum DeduceAutoResult {
|
||||
DAR_Succeeded,
|
||||
DAR_Failed,
|
||||
DAR_FailedAlreadyDiagnosed
|
||||
};
|
||||
|
||||
DeduceAutoResult DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer,
|
||||
TypeSourceInfo *&Result);
|
||||
void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
|
||||
|
||||
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
|
||||
|
|
|
@ -6011,7 +6011,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
||||
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
|
||||
TypeSourceInfo *DeducedType = 0;
|
||||
if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
|
||||
if (DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType) ==
|
||||
DAR_Failed)
|
||||
DiagnoseAutoDeductionFailure(VDecl, Init);
|
||||
if (!DeducedType) {
|
||||
RealDecl->setInvalidDecl();
|
||||
|
|
|
@ -5809,12 +5809,13 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
|
|||
CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
|
||||
if (TemplateClass->getIdentifier() !=
|
||||
&PP.getIdentifierTable().get("initializer_list") ||
|
||||
!TemplateClass->getDeclContext()->Equals(getStdNamespace()))
|
||||
!getStdNamespace()->InEnclosingNamespaceSetOf(
|
||||
TemplateClass->getDeclContext()))
|
||||
return false;
|
||||
// This is a template called std::initializer_list, but is it the right
|
||||
// template?
|
||||
TemplateParameterList *Params = Template->getTemplateParameters();
|
||||
if (Params->size() != 1)
|
||||
if (Params->getMinRequiredArguments() != 1)
|
||||
return false;
|
||||
if (!isa<TemplateTypeParmDecl>(Params->getParam(0)))
|
||||
return false;
|
||||
|
@ -5857,7 +5858,8 @@ static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
|
|||
// We found some template called std::initializer_list. Now verify that it's
|
||||
// correct.
|
||||
TemplateParameterList *Params = Template->getTemplateParameters();
|
||||
if (Params->size() != 1 || !isa<TemplateTypeParmDecl>(Params->getParam(0))) {
|
||||
if (Params->getMinRequiredArguments() != 1 ||
|
||||
!isa<TemplateTypeParmDecl>(Params->getParam(0))) {
|
||||
S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
|
||||
return 0;
|
||||
}
|
||||
|
@ -9102,7 +9104,8 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
|
|||
|
||||
Expr *Init = Exprs.get()[0];
|
||||
TypeSourceInfo *DeducedType = 0;
|
||||
if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
|
||||
if (DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType) ==
|
||||
DAR_Failed)
|
||||
DiagnoseAutoDeductionFailure(VDecl, Init);
|
||||
if (!DeducedType) {
|
||||
RealDecl->setInvalidDecl();
|
||||
|
|
|
@ -952,7 +952,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
<< AllocType << TypeRange);
|
||||
}
|
||||
TypeSourceInfo *DeducedType = 0;
|
||||
if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType))
|
||||
if (DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType) ==
|
||||
DAR_Failed)
|
||||
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
|
||||
<< AllocType
|
||||
<< ConstructorArgs.get()[0]->getType()
|
||||
|
|
|
@ -4111,7 +4111,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
|
|||
Result.setBad(BadConversionSequence::no_conversion, From, ToType);
|
||||
Result.setListInitializationSequence();
|
||||
|
||||
// We need a complete type for what follows. Incomplete types can bever be
|
||||
// We need a complete type for what follows. Incomplete types can never be
|
||||
// initialized from init lists.
|
||||
if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()))
|
||||
return Result;
|
||||
|
|
|
@ -1201,7 +1201,8 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
|
|||
// AddInitializerToDecl, so we can produce a more suitable diagnostic.
|
||||
TypeSourceInfo *InitTSI = 0;
|
||||
if ((!isa<InitListExpr>(Init) && Init->getType()->isVoidType()) ||
|
||||
!SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI))
|
||||
SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI) ==
|
||||
Sema::DAR_Failed)
|
||||
SemaRef.Diag(Loc, diag) << Init->getType();
|
||||
if (!InitTSI) {
|
||||
Decl->setInvalidDecl();
|
||||
|
|
|
@ -3376,20 +3376,18 @@ namespace {
|
|||
/// 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.
|
||||
bool
|
||||
Sema::DeduceAutoResult
|
||||
Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
|
||||
TypeSourceInfo *&Result) {
|
||||
if (Init->getType()->isNonOverloadPlaceholderType()) {
|
||||
ExprResult result = CheckPlaceholderExpr(Init);
|
||||
if (result.isInvalid()) return false;
|
||||
if (result.isInvalid()) return DAR_FailedAlreadyDiagnosed;
|
||||
Init = result.take();
|
||||
}
|
||||
|
||||
if (Init->isTypeDependent()) {
|
||||
Result = Type;
|
||||
return true;
|
||||
return DAR_Succeeded;
|
||||
}
|
||||
|
||||
SourceLocation Loc = Init->getExprLoc();
|
||||
|
@ -3418,7 +3416,7 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
|
|||
if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
|
||||
FuncParam, InitType, Init,
|
||||
TDF))
|
||||
return false;
|
||||
return DAR_Failed;
|
||||
|
||||
TemplateDeductionInfo Info(Context, Loc);
|
||||
|
||||
|
@ -3428,22 +3426,22 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
|
|||
if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
|
||||
InitList->getInit(i)->getType(),
|
||||
Info, Deduced, TDF))
|
||||
return false;
|
||||
return DAR_Failed;
|
||||
}
|
||||
} else {
|
||||
if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
|
||||
InitType, Info, Deduced, TDF))
|
||||
return false;
|
||||
return DAR_Failed;
|
||||
}
|
||||
|
||||
QualType DeducedType = Deduced[0].getAsType();
|
||||
if (DeducedType.isNull())
|
||||
return false;
|
||||
return DAR_Failed;
|
||||
|
||||
if (InitList) {
|
||||
DeducedType = BuildStdInitializerList(DeducedType, Loc);
|
||||
if (DeducedType.isNull())
|
||||
return false;
|
||||
return DAR_FailedAlreadyDiagnosed;
|
||||
}
|
||||
|
||||
Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
|
||||
|
@ -3455,10 +3453,10 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
|
|||
Sema::OriginalCallArg(FuncParam,0,InitType),
|
||||
Result->getType())) {
|
||||
Result = 0;
|
||||
return false;
|
||||
return DAR_Failed;
|
||||
}
|
||||
|
||||
return true;
|
||||
return DAR_Succeeded;
|
||||
}
|
||||
|
||||
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
|
||||
|
|
|
@ -92,8 +92,7 @@ namespace PR10939 {
|
|||
template<typename T> T g(T);
|
||||
|
||||
void f(X *x) {
|
||||
// FIXME: we should really only get the first diagnostic here.
|
||||
auto value = x->method; // expected-error {{reference to non-static member function must be called}} expected-error{{variable 'value' with type 'auto' has incompatible initializer of type '<bound member function type>'}}
|
||||
auto value = x->method; // expected-error {{reference to non-static member function must be called}}
|
||||
if (value) { }
|
||||
|
||||
auto funcptr = &g<int>;
|
||||
|
@ -101,4 +100,5 @@ namespace PR10939 {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: if the initializer is a braced-init-list, deduce auto as std::initializer_list<T>.
|
||||
// if the initializer is a braced-init-list, deduce auto as std::initializer_list<T>:
|
||||
// see SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
|
||||
|
||||
// This must obviously come before the definition of std::initializer_list.
|
||||
void missing_initializerlist() {
|
||||
auto l = {1, 2, 3, 4}; // expected-error {{std::initializer_list was not found}}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
typedef decltype(sizeof(int)) size_t;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ struct X {
|
|||
- (int) z;
|
||||
@end
|
||||
void test2(Test2 *a) {
|
||||
auto y = a.y; // expected-error {{expected getter method not found on object of type 'Test2 *'}} expected-error {{variable 'y' with type 'auto' has incompatible initializer of type}}
|
||||
auto y = a.y; // expected-error {{expected getter method not found on object of type 'Test2 *'}}
|
||||
auto z = a.z;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue