forked from OSchip/llvm-project
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:
parent
db45278cbd
commit
8ec5173f9a
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue