From b832f6dea893f25b40500a04781286236281cb20 Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Mon, 23 Jan 2012 22:09:39 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148735 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 11 ++++++++-- lib/Sema/SemaDecl.cpp | 3 ++- lib/Sema/SemaDeclCXX.cpp | 11 ++++++---- lib/Sema/SemaExprCXX.cpp | 3 ++- lib/Sema/SemaOverload.cpp | 2 +- lib/Sema/SemaStmt.cpp | 3 ++- lib/Sema/SemaTemplateDeduction.cpp | 22 +++++++++---------- .../dcl.spec/dcl.type/dcl.spec.auto/p6.cpp | 6 ++--- .../cxx0x-initializer-stdinitializerlist.cpp | 5 +++++ test/SemaObjCXX/properties.mm | 2 +- 10 files changed, 42 insertions(+), 26 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 754b2906b3..309d191aa9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 696e84234c..980c59c4c9 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 983e815f60..b706cdc9fb 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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(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(Params->getParam(0))) { + if (Params->getMinRequiredArguments() != 1 || + !isa(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(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 3d155a5cf3..bea0954c6f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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() diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 931573bb29..fac3c26d0e 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 2d843393a2..86bb74040a 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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(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(); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 0d74f24f4d..adc6994fb0 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -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) { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp index aa22b8f56b..d327efcc20 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -92,8 +92,7 @@ namespace PR10939 { template 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 ''}} + auto value = x->method; // expected-error {{reference to non-static member function must be called}} if (value) { } auto funcptr = &g; @@ -101,4 +100,5 @@ namespace PR10939 { } } -// TODO: if the initializer is a braced-init-list, deduce auto as std::initializer_list. +// if the initializer is a braced-init-list, deduce auto as std::initializer_list: +// see SemaCXX/cxx0x-initializer-stdinitializerlist.cpp diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index 47ceaf0b83..fe3cd8fc3a 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/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; diff --git a/test/SemaObjCXX/properties.mm b/test/SemaObjCXX/properties.mm index d8d92e5687..ac780c023b 100644 --- a/test/SemaObjCXX/properties.mm +++ b/test/SemaObjCXX/properties.mm @@ -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; } -- 2.40.0