"trailing return type may not be nested within parentheses">;
def err_auto_var_deduction_failure : Error<
"variable %0 with type %1 has incompatible initializer of type %2">;
+def err_auto_var_deduction_failure_from_init_list : Error<
+ "cannot deduce actual type for variable %0 with type %1 from initializer list">;
def err_auto_new_deduction_failure : Error<
"new expression for type %0 has incompatible constructor argument of type %1">;
def err_auto_different_deductions : Error<
"'auto' deduced as %0 in declaration of %1 and deduced as %2 in declaration of %3">;
+def err_implied_std_initializer_list_not_found : Error<
+ "cannot deduce type of initializer list because std::initializer_list was "
+ "not found; include <initializer_list>">;
+def err_malformed_std_initializer_list : Error<
+ "std::initializer_list must be a class template with a single type parameter">;
// C++11 override control
def override_keyword_only_allowed_on_virtual_member_functions : Error<
/// it is and Element is not NULL, assigns the element type to Element.
bool isStdInitializerList(QualType Ty, QualType *Element);
+ /// \brief Looks for the std::initializer_list template and instantiates it
+ /// with Element, or emits an error if it's not found.
+ ///
+ /// \returns The instantiated template, or null on error.
+ QualType BuildStdInitializerList(QualType Element, SourceLocation Loc);
+
Decl *ActOnUsingDirective(Scope *CurScope,
SourceLocation UsingLoc,
SourceLocation NamespcLoc,
bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer,
TypeSourceInfo *&Result);
+ void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
TypeSourceInfo *DeducedType = 0;
if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
- Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
- << VDecl->getDeclName() << VDecl->getType() << Init->getType()
- << Init->getSourceRange();
+ DiagnoseAutoDeductionFailure(VDecl, Init);
if (!DeducedType) {
RealDecl->setInvalidDecl();
return;
return true;
}
+static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
+ NamespaceDecl *Std = S.getStdNamespace();
+ if (!Std) {
+ S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
+ return 0;
+ }
+
+ LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"),
+ Loc, Sema::LookupOrdinaryName);
+ if (!S.LookupQualifiedName(Result, Std)) {
+ S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
+ return 0;
+ }
+ ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>();
+ if (!Template) {
+ Result.suppressDiagnostics();
+ // We found something weird. Complain about the first thing we found.
+ NamedDecl *Found = *Result.begin();
+ S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list);
+ return 0;
+ }
+
+ // 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))) {
+ S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
+ return 0;
+ }
+
+ return Template;
+}
+
+QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
+ if (!StdInitializerList) {
+ StdInitializerList = LookupStdInitializerList(*this, Loc);
+ if (!StdInitializerList)
+ return QualType();
+ }
+
+ TemplateArgumentListInfo Args(Loc, Loc);
+ Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element),
+ Context.getTrivialTypeSourceInfo(Element,
+ Loc)));
+ return Context.getCanonicalType(
+ CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args));
+}
+
/// \brief Determine whether a using statement is in a context where it will be
/// apply in all contexts.
static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
Expr *Init = Exprs.get()[0];
TypeSourceInfo *DeducedType = 0;
if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
- Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
- << VDecl->getDeclName() << VDecl->getType() << Init->getType()
- << Init->getSourceRange();
+ DiagnoseAutoDeductionFailure(VDecl, Init);
if (!DeducedType) {
RealDecl->setInvalidDecl();
return;
// Deduce the type for the iterator variable now rather than leaving it to
// AddInitializerToDecl, so we can produce a more suitable diagnostic.
TypeSourceInfo *InitTSI = 0;
- if (Init->getType()->isVoidType() ||
+ if ((!isa<InitListExpr>(Init) && Init->getType()->isVoidType()) ||
!SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI))
SemaRef.Diag(Loc, diag) << Init->getType();
if (!InitTSI) {
return false;
TemplateDeductionInfo Info(Context, Loc);
- if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
- InitType, Info, Deduced, TDF))
- return false;
+
+ InitListExpr * InitList = dyn_cast<InitListExpr>(Init);
+ if (InitList) {
+ for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
+ if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
+ InitList->getInit(i)->getType(),
+ Info, Deduced, TDF))
+ return false;
+ }
+ } else {
+ if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
+ InitType, Info, Deduced, TDF))
+ return false;
+ }
QualType DeducedType = Deduced[0].getAsType();
if (DeducedType.isNull())
return false;
-
+
+ if (InitList) {
+ DeducedType = BuildStdInitializerList(DeducedType, Loc);
+ if (DeducedType.isNull())
+ return false;
+ }
+
Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
-
+
// Check that the deduced argument type is compatible with the original
// argument type per C++ [temp.deduct.call]p4.
- if (Result &&
+ if (!InitList && Result &&
CheckOriginalCallArgDeduction(*this,
Sema::OriginalCallArg(FuncParam,0,InitType),
Result->getType())) {
return true;
}
+void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
+ if (isa<InitListExpr>(Init))
+ Diag(VDecl->getLocation(),
+ diag::err_auto_var_deduction_failure_from_init_list)
+ << VDecl->getDeclName() << VDecl->getType() << Init->getSourceRange();
+ else
+ Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+ << VDecl->getDeclName() << VDecl->getType() << Init->getType()
+ << Init->getSourceRange();
+}
+
static void
MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
bool OnlyDeduced,
deduce_ref({1, 2.0}); // expected-error {{no matching function}}
}
+
+void auto_deduction() {
+ auto l = {1, 2, 3, 4};
+ static_assert(same_type<decltype(l), std::initializer_list<int>>::value, "");
+ auto bl = {1, 2.0}; // expected-error {{cannot deduce}}
+
+ for (int i : {1, 2, 3, 4}) {}
+}
};
}
-namespace integral {
-
- void initializer_list() {
- auto l = {1, 2, 3, 4};
- static_assert(same_type<decltype(l), std::initializer_list<int>>::value, "");
- auto bl = {1, 2.0}; // expected-error {{cannot deduce}}
-
- for (int i : {1, 2, 3, 4}) {}
- }
-
-}
-
namespace objects {
struct X1 { X1(int); };