Use the new-initialization code for initializing scalars with a

function-style cast. Previously, we had a (redundant, incorrect)
semantic-checking path for non-class types, which allowed
value-initialization of a reference type and then crashed.

llvm-svn: 113415
This commit is contained in:
Douglas Gregor 2010-09-08 21:40:08 +00:00
parent db45278cbd
commit 8ec5173f9a
6 changed files with 27 additions and 43 deletions

View File

@ -615,41 +615,17 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
RParenLoc));
}
if (Ty->isRecordType()) {
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
InitializationKind Kind
= NumExprs ? InitializationKind::CreateDirect(TyBeginLoc,
LParenLoc, RParenLoc)
: InitializationKind::CreateValue(TyBeginLoc,
LParenLoc, RParenLoc);
InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs));
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
InitializationKind Kind
= NumExprs ? InitializationKind::CreateDirect(TyBeginLoc,
LParenLoc, RParenLoc)
: InitializationKind::CreateValue(TyBeginLoc,
LParenLoc, RParenLoc);
InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs));
// FIXME: Improve AST representation?
return move(Result);
}
// C++ [expr.type.conv]p1:
// If the expression list specifies more than a single value, the type shall
// be a class with a suitably declared constructor.
//
if (NumExprs > 1)
return ExprError(Diag(PP.getLocForEndOfToken(Exprs[0]->getLocEnd()),
diag::err_builtin_func_cast_more_than_one_arg)
<< FullRange);
assert(NumExprs == 0 && "Expected 0 expressions");
// FIXME: Why doesn't this go through the new-initialization code?
// C++ [expr.type.conv]p2:
// The expression T(), where T is a simple-type-specifier for a non-array
// complete object type or the (possibly cv-qualified) void type, creates an
// rvalue of the specified type, which is value-initialized.
//
exprs.release();
return Owned(new (Context) CXXScalarValueInitExpr(
TInfo->getType().getNonLValueExprType(Context),
TInfo, RParenLoc));
// FIXME: Improve AST representation?
return move(Result);
}

View File

@ -4094,13 +4094,18 @@ bool InitializationSequence::Diagnose(Sema &S,
SourceRange R;
if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
R = SourceRange(InitList->getInit(1)->getLocStart(),
R = SourceRange(InitList->getInit(0)->getLocEnd(),
InitList->getLocEnd());
else
R = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
else
R = SourceRange(Args[0]->getLocEnd(), Args[NumArgs - 1]->getLocEnd());
S.Diag(Kind.getLocation(), diag::err_excess_initializers)
<< /*scalar=*/2 << R;
R.setBegin(S.PP.getLocForEndOfToken(R.getBegin()));
if (Kind.isCStyleOrFunctionalCast())
S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
<< R;
else
S.Diag(Kind.getLocation(), diag::err_excess_initializers)
<< /*scalar=*/2 << R;
break;
}

View File

@ -9,7 +9,7 @@ void f() {
T(a)->m = 7;
int(a)++; // expected-error {{expression is not assignable}}
__extension__ int(a)++; // expected-error {{expression is not assignable}}
__typeof(int)(a,5)<<a; // expected-error {{function-style cast to a builtin type can only take one argument}}
__typeof(int)(a,5)<<a; // expected-error {{excess elements in scalar initializer}}
void(a), ++a;
if (int(a)+1) {}
for (int(a)+1;;) {} // expected-warning {{expression result unused}}

View File

@ -23,7 +23,7 @@ void test_cxx_functional_value_init() {
void test_cxx_function_cast_multi() {
(void)NoValueInit(0, 0);
(void)NoValueInit(0, 0, 0); // expected-error{{no matching constructor for initialization}}
(void)int(1, 2); // expected-error{{function-style cast to a builtin type can only take one argument}}
(void)int(1, 2); // expected-error{{excess elements in scalar initializer}}
}
@ -314,4 +314,7 @@ void crash_on_invalid_1()
{
typedef itn Typo; // expected-error {{unknown type name 'itn'}}
(void)Typo(1); // used to crash
typedef int &int_ref;
(void)int_ref(); // expected-error {{reference to type 'int' requires an initializer}}
}

View File

@ -78,7 +78,7 @@ namespace a {
typedef int f2_type(int, int);
void test_f2() {
::f2_type(1, 2); // expected-error {{function-style cast to a builtin type can only take one argument}}
::f2_type(1, 2); // expected-error {{excess elements in scalar initializer}}
}
}

View File

@ -2,7 +2,7 @@
void f() {
float v1 = float(1);
int v2 = typeof(int)(1,2); // expected-error {{function-style cast to a builtin type can only take one argument}}
int v2 = typeof(int)(1,2); // expected-error {{excess elements in scalar initializer}}
typedef int arr[];
int v3 = arr(); // expected-error {{array types cannot be value-initialized}}
int v4 = int();