[cfe-commits] r150346 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Parse/ParseExprCXX.cpp lib/Sema/SemaCast.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/cxx0x-initializer-aggregates.cpp test/SemaCXX/cxx0x-initializer-scalars.cpp test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp test/SemaCXX/cxx98-compat.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Feb 12 10:41:05 PST 2012
Author: cornedbee
Date: Sun Feb 12 12:41:05 2012
New Revision: 150346
URL: http://llvm.org/viewvc/llvm-project?rev=150346&view=rev
Log:
Proper initializer list support for new expressions and type construct expressions. Array new still missing.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/SemaCast.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
cfe/trunk/test/SemaCXX/cxx98-compat.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Feb 12 12:41:05 2012
@@ -1232,6 +1232,8 @@
"declaration of variable %0 with type %1 requires an initializer">;
def err_auto_new_requires_ctor_arg : Error<
"new expression for type %0 requires a constructor argument">;
+def err_auto_new_requires_parens : Error<
+ "new expression for type %0 cannot use list-initialization">;
def err_auto_var_init_no_expression : Error<
"initializer for variable %0 with type %1 is empty">;
def err_auto_var_init_multiple_expressions : Error<
@@ -1257,6 +1259,10 @@
"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">;
+def warn_dangling_std_initializer_list : Warning<
+ "array backing the initializer list will be destroyed at the end of "
+ "%select{the full-expression|the constructor}0">,
+ InGroup<DiagGroup<"dangling-initializer-list">>;
// C++11 override control
def override_keyword_only_allowed_on_virtual_member_functions : Error<
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sun Feb 12 12:41:05 2012
@@ -1151,10 +1151,13 @@
&& "Expected '(' or '{'!");
if (Tok.is(tok::l_brace)) {
-
- // FIXME: Convert to a proper type construct expression.
- return ParseBraceInitializer();
-
+ ExprResult Init = ParseBraceInitializer();
+ if (Init.isInvalid())
+ return Init;
+ Expr *InitList = Init.take();
+ return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(),
+ MultiExprArg(&InitList, 1),
+ SourceLocation());
} else {
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Sun Feb 12 12:41:05 2012
@@ -77,7 +77,7 @@
void CheckReinterpretCast();
void CheckStaticCast();
void CheckDynamicCast();
- void CheckCXXCStyleCast(bool FunctionalCast);
+ void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
void CheckCStyleCast();
/// Complete an apparently-successful cast operation that yields
@@ -190,15 +190,15 @@
QualType DestType,
Sema::CheckedConversionKind CCK,
const SourceRange &OpRange,
- unsigned &msg,
- CastKind &Kind);
+ unsigned &msg, CastKind &Kind,
+ bool ListInitialization);
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType,
Sema::CheckedConversionKind CCK,
const SourceRange &OpRange,
- unsigned &msg,
- CastKind &Kind,
- CXXCastPath &BasePath);
+ unsigned &msg, CastKind &Kind,
+ CXXCastPath &BasePath,
+ bool ListInitialization);
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, unsigned &msg);
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
@@ -752,7 +752,7 @@
unsigned msg = diag::err_bad_cxx_cast_generic;
TryCastResult tcr
= TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg,
- Kind, BasePath);
+ Kind, BasePath, /*ListInitialization=*/false);
if (tcr != TC_Success && msg != 0) {
if (SrcExpr.isInvalid())
return;
@@ -782,8 +782,8 @@
QualType DestType,
Sema::CheckedConversionKind CCK,
const SourceRange &OpRange, unsigned &msg,
- CastKind &Kind,
- CXXCastPath &BasePath) {
+ CastKind &Kind, CXXCastPath &BasePath,
+ bool ListInitialization) {
// Determine whether we have the semantics of a C-style cast.
bool CStyle
= (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
@@ -808,23 +808,23 @@
// C++ 5.2.9p5, reference downcast.
// See the function for details.
// DR 427 specifies that this is to be applied before paragraph 2.
- tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange,
- msg, Kind, BasePath);
+ tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle,
+ OpRange, msg, Kind, BasePath);
if (tcr != TC_NotApplicable)
return tcr;
// C++0x [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
- tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath,
- msg);
+ tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
+ BasePath, msg);
if (tcr != TC_NotApplicable)
return tcr;
// C++ 5.2.9p2: An expression e can be explicitly converted to a type T
// [...] if the declaration "T t(e);" is well-formed, [...].
tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg,
- Kind);
+ Kind, ListInitialization);
if (SrcExpr.isInvalid())
return TC_Failed;
if (tcr != TC_NotApplicable)
@@ -1295,7 +1295,7 @@
TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
Sema::CheckedConversionKind CCK,
const SourceRange &OpRange, unsigned &msg,
- CastKind &Kind) {
+ CastKind &Kind, bool ListInitialization) {
if (DestType->isRecordType()) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
diag::err_bad_dynamic_cast_incomplete)) {
@@ -1304,15 +1304,13 @@
}
}
- // FIXME: doesn't correctly identify T({1})
- bool InitList = isa<InitListExpr>(SrcExpr.get());
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
InitializationKind InitKind
= (CCK == Sema::CCK_CStyleCast)
? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange,
- InitList)
+ ListInitialization)
: (CCK == Sema::CCK_FunctionalCast)
- ? InitializationKind::CreateFunctionalCast(OpRange, InitList)
+ ? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization)
: InitializationKind::CreateCast(OpRange);
Expr *SrcExprRaw = SrcExpr.get();
InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1);
@@ -1756,7 +1754,8 @@
return TC_Success;
}
-void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) {
+void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
+ bool ListInitialization) {
// Handle placeholders.
if (isPlaceholder()) {
// C-style casts can resolve __unknown_any types.
@@ -1839,7 +1838,7 @@
if (tcr == TC_NotApplicable) {
// ... or if that is not possible, a static_cast, ignoring const, ...
tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
- msg, Kind, BasePath);
+ msg, Kind, BasePath, ListInitialization);
if (SrcExpr.isInvalid())
return;
@@ -2073,7 +2072,8 @@
Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
if (getLangOptions().CPlusPlus) {
- Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false);
+ Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false,
+ isa<InitListExpr>(CastExpr));
} else {
Op.CheckCStyleCast();
}
@@ -2090,11 +2090,14 @@
SourceLocation LPLoc,
Expr *CastExpr,
SourceLocation RPLoc) {
+ bool ListInitialization = LPLoc.isInvalid();
+ assert((!ListInitialization || isa<InitListExpr>(CastExpr)) &&
+ "List initialization must have initializer list as expression.");
CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
- Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true);
+ Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true, ListInitialization);
if (Op.SrcExpr.isInvalid())
return ExprError();
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Feb 12 12:41:05 2012
@@ -767,7 +767,6 @@
unsigned NumExprs = exprs.size();
Expr **Exprs = (Expr**)exprs.get();
SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
- SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
if (Ty->isDependentType() ||
CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
@@ -779,6 +778,12 @@
RParenLoc));
}
+ bool ListInitialization = LParenLoc.isInvalid();
+ assert((!ListInitialization || (NumExprs == 1 && isa<InitListExpr>(Exprs[0])))
+ && "List initialization must have initializer list as expression.");
+ SourceRange FullRange = SourceRange(TyBeginLoc,
+ ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
+
if (Ty->isArrayType())
return ExprError(Diag(TyBeginLoc,
diag::err_value_init_for_array_type) << FullRange);
@@ -872,11 +877,24 @@
return (del->getNumParams() == 2);
}
-/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.:
+/// \brief Parsed a C++ 'new' expression (C++ 5.3.4).
+
+/// E.g.:
/// @code new (memory) int[size][4] @endcode
/// or
/// @code ::new Foo(23, "hello") @endcode
-/// For the interpretation of this heap of arguments, consult the base version.
+///
+/// \param StartLoc The first location of the expression.
+/// \param UseGlobal True if 'new' was prefixed with '::'.
+/// \param PlacementLParen Opening paren of the placement arguments.
+/// \param PlacementArgs Placement new arguments.
+/// \param PlacementRParen Closing paren of the placement arguments.
+/// \param TypeIdParens If the type is in parens, the source range.
+/// \param D The type to be allocated, as well as array dimensions.
+/// \param ConstructorLParen Opening paren of the constructor args, empty if
+/// initializer-list syntax is used.
+/// \param ConstructorArgs Constructor/initialization arguments.
+/// \param ConstructorRParen Closing paren of the constructor args.
ExprResult
Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
@@ -968,21 +986,25 @@
diag::err_auto_new_ctor_multiple_expressions)
<< AllocType << TypeRange);
}
+ Expr *Deduce = ConstructorArgs.get()[0];
+ if (ConstructorLParen.isInvalid()) {
+ return ExprError(Diag(Deduce->getSourceRange().getBegin(),
+ diag::err_auto_new_requires_parens)
+ << AllocType << TypeRange);
+ }
TypeSourceInfo *DeducedType = 0;
- if (DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType) ==
+ if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) ==
DAR_Failed)
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
- << AllocType
- << ConstructorArgs.get()[0]->getType()
- << TypeRange
- << ConstructorArgs.get()[0]->getSourceRange());
+ << AllocType << Deduce->getType()
+ << TypeRange << Deduce->getSourceRange());
if (!DeducedType)
return ExprError();
AllocTypeInfo = DeducedType;
AllocType = AllocTypeInfo->getType();
}
-
+
// Per C++0x [expr.new]p5, the type being constructed may be a
// typedef of an array type.
if (!ArraySize) {
@@ -998,6 +1020,17 @@
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
return ExprError();
+ bool ListInitialization = ConstructorLParen.isInvalid() &&
+ ConstructorArgs.size() > 0;
+ assert((!ListInitialization || (ConstructorArgs.size() == 1 &&
+ isa<InitListExpr>(ConstructorArgs.get()[0])))
+ && "List initialization means a braced-init-list for arguments.");
+ if (ListInitialization && isStdInitializerList(AllocType, 0)) {
+ Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
+ diag::warn_dangling_std_initializer_list)
+ << /*at end of FE*/0 << ConstructorArgs.get()[0]->getSourceRange();
+ }
+
// In ARC, infer 'retaining' for the allocated
if (getLangOptions().ObjCAutoRefCount &&
AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -1153,7 +1186,7 @@
}
}
- bool Init = ConstructorLParen.isValid();
+ bool Init = ConstructorLParen.isValid() || ConstructorArgs.size() > 0;
// --- Choosing a constructor ---
CXXConstructorDecl *Constructor = 0;
bool HadMultipleCandidates = false;
@@ -1172,7 +1205,7 @@
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
- // C++0x [expr.new]p15:
+ // C++11 [expr.new]p15:
// A new-expression that creates an object of type T initializes that
// object as follows:
InitializationKind Kind
@@ -1182,9 +1215,12 @@
= !Init? InitializationKind::CreateDefault(TypeRange.getBegin())
// - Otherwise, the new-initializer is interpreted according to the
// initialization rules of 8.5 for direct-initialization.
- : InitializationKind::CreateDirect(TypeRange.getBegin(),
- ConstructorLParen,
- ConstructorRParen);
+ : ListInitialization ? InitializationKind::CreateDirectList(
+ TypeRange.getBegin())
+ : InitializationKind::CreateDirect(
+ TypeRange.getBegin(),
+ ConstructorLParen,
+ ConstructorRParen);
InitializedEntity Entity
= InitializedEntity::InitializeNew(StartLoc, AllocType);
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp Sun Feb 12 12:41:05 2012
@@ -27,6 +27,13 @@
S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
}
+ void bracing_new() {
+ new S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
+ new S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
+ new S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
+ new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
+ }
+
struct String {
String(const char*);
};
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Sun Feb 12 12:41:05 2012
@@ -25,7 +25,7 @@
}
void inline_init() {
- (void) int{1};
+ auto v = int{1};
(void) new int{1};
}
@@ -59,5 +59,7 @@
void edge_cases() {
// FIXME: very poor error message
int a({0}); // expected-error {{cannot initialize}}
+ (void) int({0}); // expected-error {{functional-style cast}}
+ new int({0}); // expected-error {{cannot initialize}}
}
}
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Sun Feb 12 12:41:05 2012
@@ -122,3 +122,8 @@
for (int i : {1, 2, 3, 4}) {}
}
+
+void dangle() {
+ new auto{1, 2, 3}; // expected-error {{cannot use list-initialization}}
+ new std::initializer_list<int>{1, 2, 3}; // expected-warning {{at the end of the full-expression}}
+}
Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Sun Feb 12 12:41:05 2012
@@ -41,7 +41,8 @@
int InitList() {
(void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
// expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
- (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+ (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
+ // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
}
More information about the cfe-commits
mailing list