def warn_cxx98_compat_inline_namespace : Warning<
"inline namespaces are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
-def err_generalized_initializer_lists : Error<
- "generalized initializer lists are a C++11 extension unsupported in Clang">;
def ext_generalized_initializer_lists : ExtWarn<
- "generalized initializer lists are a C++11 extension unsupported in Clang">,
+ "generalized initializer lists are a C++11 extension">,
InGroup<CXX11>;
def warn_cxx98_compat_generalized_initializer_lists : Warning<
"generalized initializer lists are incompatible with C++98">,
DefaultError, InGroup<ReturnType>;
def ext_return_has_void_expr : Extension<
"void %select{function|method}1 %0 should not return void expression">;
+def err_return_init_list : Error<
+ "%select{void function|void method|constructor|destructor}1 %0 "
+ "must not return a value">;
def warn_noreturn_function_has_return_expr : Warning<
"function %0 declared 'noreturn' should not return">,
InGroup<DiagGroup<"invalid-noreturn">>;
if (Init.isInvalid())
SkipUntil(tok::comma, true, true);
else if (ThisDecl)
- Actions.AddInitializerToDecl(ThisDecl, Init.get(), false,
+ Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(),
DS.getTypeSpecType() == DeclSpec::TST_auto);
} else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) {
// No initializer.
///
/// pure-specifier:
/// '= 0'
-///
+///
/// brace-or-equal-initializer:
/// '=' initializer-expression
-/// braced-init-list [TODO]
-///
+/// braced-init-list
+///
/// initializer-clause:
/// assignment-expression
-/// braced-init-list [TODO]
-///
+/// braced-init-list
+///
/// defaulted/deleted function-definition:
/// '=' 'default'
/// '=' 'delete'
return ExprResult();
}
- return ParseInitializer();
- } else
- return ExprError(Diag(Tok, diag::err_generalized_initializer_lists));
+ }
+ return ParseInitializer();
}
/// ParseCXXMemberSpecification - Parse the class definition.
return StmtError();
}
- // FIXME: This is a hack to allow something like C++0x's generalized
- // initializer lists, but only enough of this feature to allow Clang to
- // parse libstdc++ 4.5's headers.
if (Tok.is(tok::l_brace) && getLang().CPlusPlus) {
R = ParseInitializer();
if (R.isUsable())
ExprResult Init = InitExpr;
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) {
- Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list)
+ Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list)
<< /*at end of ctor*/1 << InitExpr->getSourceRange();
}
- // FIXME: if there is no EqualLoc, this is list-initialization.
- Init = PerformCopyInitialization(
- InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr);
+ Expr **Inits = &InitExpr;
+ unsigned NumInits = 1;
+ InitializedEntity Entity = InitializedEntity::InitializeMember(FD);
+ InitializationKind Kind = EqualLoc.isInvalid()
+ ? InitializationKind::CreateDirectList(InitExpr->getLocStart())
+ : InitializationKind::CreateCopy(InitExpr->getLocStart(), EqualLoc);
+ InitializationSequence Seq(*this, Entity, Kind, Inits, NumInits);
+ Init = Seq.Perform(*this, Entity, Kind, MultiExprArg(Inits, NumInits));
if (Init.isInvalid()) {
FD->setInvalidDecl();
return;
ReturnStmt *Result = 0;
if (FnRetType->isVoidType()) {
if (RetValExp) {
- if (!RetValExp->isTypeDependent()) {
+ if (isa<InitListExpr>(RetValExp)) {
+ // We simply never allow init lists as the return value of void
+ // functions. This is compatible because this was never allowed before,
+ // so there's no legacy code to deal with.
+ NamedDecl *CurDecl = getCurFunctionOrMethodDecl();
+ int FunctionKind = 0;
+ if (isa<ObjCMethodDecl>(CurDecl))
+ FunctionKind = 1;
+ else if (isa<CXXConstructorDecl>(CurDecl))
+ FunctionKind = 2;
+ else if (isa<CXXDestructorDecl>(CurDecl))
+ FunctionKind = 3;
+
+ Diag(ReturnLoc, diag::err_return_init_list)
+ << CurDecl->getDeclName() << FunctionKind
+ << RetValExp->getSourceRange();
+
+ // Drop the expression.
+ RetValExp = 0;
+ } else if (!RetValExp->isTypeDependent()) {
// C99 6.8.6.4p1 (ext_ since GCC warns)
unsigned D = diag::ext_return_has_expr;
if (RetValExp->getType()->isVoidType())
}
}
- CheckImplicitConversions(RetValExp, ReturnLoc);
- RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ if (RetValExp) {
+ CheckImplicitConversions(RetValExp, ReturnLoc);
+ RetValExp = MaybeCreateExprWithCleanups(RetValExp);
+ }
}
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
G(std::initializer_list<int>, T ...); // expected-note 3 {{not viable}}
};
- struct H { // expected-note 6 {{not viable}}
+ struct H { // expected-note 8 {{not viable}}
explicit H(int, int); // expected-note 3 {{not viable}}
- H(int, void*); // expected-note 3 {{not viable}}
+ H(int, void*); // expected-note 4 {{not viable}}
};
void edge_cases() {
(void) new H{1, 2};
(void) H{1, 2};
}
+
+ struct memberinit {
+ H h1{1, nullptr};
+ H h2 = {1, nullptr};
+ H h3{1, 1};
+ H h4 = {1, 1}; // expected-error {{no matching constructor}}
+ };
}
struct haslist1 {
std::initializer_list<int> il = {1, 2, 3}; // expected-warning{{at the end of the constructor}}
+ std::initializer_list<int> jl{1, 2, 3}; // expected-warning{{at the end of the constructor}}
haslist1();
};
// RUN: %clang_cc1 -fsyntax-only -verify %s
-// This test checks for a teeny tiny subset of the functionality in
-// the C++11 generalized initializer lists feature, which happens to
-// be used in libstdc++ 4.5. We accept only this syntax so that Clang
-// can handle the libstdc++ 4.5 headers.
+// Test that a very basic variation of generalized initializer returns (that
+// required for libstdc++ 4.5) is supposed in C++98.
int test0(int i) {
- return { i }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}}
+ return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}}
}
template<typename T, typename U>
T test1(U u) {
- return { u }; // expected-warning{{generalized initializer lists are a C++11 extension unsupported in Clang}}
+ return { u }; // expected-warning{{generalized initializer lists are a C++11 extension}}
}
template int test1(char);