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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113415 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index c3e2c50..5dc2713 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -615,41 +615,17 @@
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);
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 64f5ac0..fe10422 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -4094,13 +4094,18 @@
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;
}
diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp
index 4243c1c..9595fae 100644
--- a/test/SemaCXX/decl-expr-ambiguity.cpp
+++ b/test/SemaCXX/decl-expr-ambiguity.cpp
@@ -9,7 +9,7 @@
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}}
diff --git a/test/SemaCXX/functional-cast.cpp b/test/SemaCXX/functional-cast.cpp
index 2f63c20..61e4da3 100644
--- a/test/SemaCXX/functional-cast.cpp
+++ b/test/SemaCXX/functional-cast.cpp
@@ -23,7 +23,7 @@
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 @@
{
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}}
}
diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp
index dfb059a..3cd6e18 100644
--- a/test/SemaCXX/qualified-id-lookup.cpp
+++ b/test/SemaCXX/qualified-id-lookup.cpp
@@ -78,7 +78,7 @@
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}}
}
}
diff --git a/test/SemaCXX/type-convert-construct.cpp b/test/SemaCXX/type-convert-construct.cpp
index 8f92a03..479af21 100644
--- a/test/SemaCXX/type-convert-construct.cpp
+++ b/test/SemaCXX/type-convert-construct.cpp
@@ -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();