Skip to content

Commit 410cc89

Browse files
committed
[c++1z] Most of N4268 (allow constant evaluation for non-type template arguments).
We don't yet support pointer-to-member template arguments that have undergone pointer-to-member conversions, mostly because we don't have a mangling for them yet. llvm-svn: 222807
1 parent 1686e4e commit 410cc89

File tree

12 files changed

+397
-87
lines changed

12 files changed

+397
-87
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ def err_typecheck_converted_constant_expression : Error<
6464
"value of type %0 is not implicitly convertible to %1">;
6565
def err_typecheck_converted_constant_expression_disallowed : Error<
6666
"conversion from %0 to %1 is not allowed in a converted constant expression">;
67+
def err_typecheck_converted_constant_expression_indirect : Error<
68+
"conversion from %0 to %1 in converted constant expression would "
69+
"bind reference to a temporary">;
6770
def err_expr_not_cce : Error<
6871
"%select{case value|enumerator value|non-type template argument|array size}0 "
6972
"is not a constant expression">;
@@ -3293,6 +3296,10 @@ def err_template_arg_wrongtype_null_constant : Error<
32933296
def err_deduced_non_type_template_arg_type_mismatch : Error<
32943297
"deduced non-type template argument does not have the same type as the "
32953298
"its corresponding template parameter%diff{ ($ vs $)|}0,1">;
3299+
def err_non_type_template_arg_subobject : Error<
3300+
"non-type template argument refers to subobject '%0'">;
3301+
def err_non_type_template_arg_addr_label_diff : Error<
3302+
"template argument / label address difference / what did you expect?">;
32963303
def err_template_arg_not_convertible : Error<
32973304
"non-type template argument of type %0 cannot be converted to a value "
32983305
"of type %1">;
@@ -3344,6 +3351,9 @@ def err_template_arg_not_object_or_func : Error<
33443351
"non-type template argument does not refer to an object or function">;
33453352
def err_template_arg_not_pointer_to_member_form : Error<
33463353
"non-type template argument is not a pointer to member constant">;
3354+
def err_template_arg_member_ptr_base_derived_not_supported : Error<
3355+
"sorry, non-type template argument of pointer-to-member type %1 that refers "
3356+
"to member %q0 of a different class is not supported yet">;
33473357
def ext_template_arg_extra_parens : ExtWarn<
33483358
"address non-type template argument cannot be surrounded by parentheses">;
33493359
def warn_cxx98_compat_template_arg_extra_parens : Warning<

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,6 +2148,8 @@ class Sema {
21482148
};
21492149
ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
21502150
llvm::APSInt &Value, CCEKind CCE);
2151+
ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
2152+
APValue &Value, CCEKind CCE);
21512153

21522154
/// \brief Abstract base class used to perform a contextual implicit
21532155
/// conversion from an expression to any type passing a filter.

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,10 +2780,29 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
27802780
// Perform the second implicit conversion
27812781
switch (SCS.Second) {
27822782
case ICK_Identity:
2783-
// If both sides are functions (or pointers/references to them), there could
2784-
// be incompatible exception declarations.
2785-
if (CheckExceptionSpecCompatibility(From, ToType))
2786-
return ExprError();
2783+
// C++ [except.spec]p5:
2784+
// [For] assignment to and initialization of pointers to functions,
2785+
// pointers to member functions, and references to functions: the
2786+
// target entity shall allow at least the exceptions allowed by the
2787+
// source value in the assignment or initialization.
2788+
switch (Action) {
2789+
case AA_Assigning:
2790+
case AA_Initializing:
2791+
// Note, function argument passing and returning are initialization.
2792+
case AA_Passing:
2793+
case AA_Returning:
2794+
case AA_Sending:
2795+
case AA_Passing_CFAudited:
2796+
if (CheckExceptionSpecCompatibility(From, ToType))
2797+
return ExprError();
2798+
break;
2799+
2800+
case AA_Casting:
2801+
case AA_Converting:
2802+
// Casts and implicit conversions are not initialization, so are not
2803+
// checked for exception specification mismatches.
2804+
break;
2805+
}
27872806
// Nothing else to do.
27882807
break;
27892808

clang/lib/Sema/SemaOverload.cpp

Lines changed: 97 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4894,41 +4894,51 @@ static bool CheckConvertedConstantConversions(Sema &S,
48944894
// conversions are fine.
48954895
switch (SCS.Second) {
48964896
case ICK_Identity:
4897+
case ICK_NoReturn_Adjustment:
48974898
case ICK_Integral_Promotion:
4898-
case ICK_Integral_Conversion:
4899-
case ICK_Zero_Event_Conversion:
4899+
case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
49004900
return true;
49014901

49024902
case ICK_Boolean_Conversion:
49034903
// Conversion from an integral or unscoped enumeration type to bool is
4904-
// classified as ICK_Boolean_Conversion, but it's also an integral
4905-
// conversion, so it's permitted in a converted constant expression.
4904+
// classified as ICK_Boolean_Conversion, but it's also arguably an integral
4905+
// conversion, so we allow it in a converted constant expression.
4906+
//
4907+
// FIXME: Per core issue 1407, we should not allow this, but that breaks
4908+
// a lot of popular code. We should at least add a warning for this
4909+
// (non-conforming) extension.
49064910
return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() &&
49074911
SCS.getToType(2)->isBooleanType();
49084912

4913+
case ICK_Pointer_Conversion:
4914+
case ICK_Pointer_Member:
4915+
// C++1z: null pointer conversions and null member pointer conversions are
4916+
// only permitted if the source type is std::nullptr_t.
4917+
return SCS.getFromType()->isNullPtrType();
4918+
4919+
case ICK_Floating_Promotion:
4920+
case ICK_Complex_Promotion:
4921+
case ICK_Floating_Conversion:
4922+
case ICK_Complex_Conversion:
49094923
case ICK_Floating_Integral:
4924+
case ICK_Compatible_Conversion:
4925+
case ICK_Derived_To_Base:
4926+
case ICK_Vector_Conversion:
4927+
case ICK_Vector_Splat:
49104928
case ICK_Complex_Real:
4929+
case ICK_Block_Pointer_Conversion:
4930+
case ICK_TransparentUnionConversion:
4931+
case ICK_Writeback_Conversion:
4932+
case ICK_Zero_Event_Conversion:
49114933
return false;
49124934

49134935
case ICK_Lvalue_To_Rvalue:
49144936
case ICK_Array_To_Pointer:
49154937
case ICK_Function_To_Pointer:
4916-
case ICK_NoReturn_Adjustment:
4938+
llvm_unreachable("found a first conversion kind in Second");
4939+
49174940
case ICK_Qualification:
4918-
case ICK_Compatible_Conversion:
4919-
case ICK_Vector_Conversion:
4920-
case ICK_Vector_Splat:
4921-
case ICK_Derived_To_Base:
4922-
case ICK_Pointer_Conversion:
4923-
case ICK_Pointer_Member:
4924-
case ICK_Block_Pointer_Conversion:
4925-
case ICK_Writeback_Conversion:
4926-
case ICK_Floating_Promotion:
4927-
case ICK_Complex_Promotion:
4928-
case ICK_Complex_Conversion:
4929-
case ICK_Floating_Conversion:
4930-
case ICK_TransparentUnionConversion:
4931-
llvm_unreachable("unexpected second conversion kind");
4941+
llvm_unreachable("found a third conversion kind in Second");
49324942

49334943
case ICK_Num_Conversion_Kinds:
49344944
break;
@@ -4940,67 +4950,71 @@ static bool CheckConvertedConstantConversions(Sema &S,
49404950
/// CheckConvertedConstantExpression - Check that the expression From is a
49414951
/// converted constant expression of type T, perform the conversion and produce
49424952
/// the converted expression, per C++11 [expr.const]p3.
4943-
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
4944-
llvm::APSInt &Value,
4945-
CCEKind CCE) {
4946-
assert(LangOpts.CPlusPlus11 && "converted constant expression outside C++11");
4947-
assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
4948-
4949-
if (checkPlaceholderForOverload(*this, From))
4953+
static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
4954+
QualType T, APValue &Value,
4955+
Sema::CCEKind CCE,
4956+
bool RequireInt) {
4957+
assert(S.getLangOpts().CPlusPlus11 &&
4958+
"converted constant expression outside C++11");
4959+
4960+
if (checkPlaceholderForOverload(S, From))
49504961
return ExprError();
49514962

4952-
// C++11 [expr.const]p3 with proposed wording fixes:
4953-
// A converted constant expression of type T is a core constant expression,
4954-
// implicitly converted to a prvalue of type T, where the converted
4955-
// expression is a literal constant expression and the implicit conversion
4956-
// sequence contains only user-defined conversions, lvalue-to-rvalue
4957-
// conversions, integral promotions, and integral conversions other than
4958-
// narrowing conversions.
4963+
// C++1z [expr.const]p3:
4964+
// A converted constant expression of type T is an expression,
4965+
// implicitly converted to type T, where the converted
4966+
// expression is a constant expression and the implicit conversion
4967+
// sequence contains only [... list of conversions ...].
49594968
ImplicitConversionSequence ICS =
4960-
TryImplicitConversion(From, T,
4969+
TryCopyInitialization(S, From, T,
49614970
/*SuppressUserConversions=*/false,
4962-
/*AllowExplicit=*/false,
49634971
/*InOverloadResolution=*/false,
4964-
/*CStyle=*/false,
4965-
/*AllowObjcWritebackConversion=*/false);
4972+
/*AllowObjcWritebackConversion=*/false,
4973+
/*AllowExplicit=*/false);
49664974
StandardConversionSequence *SCS = nullptr;
49674975
switch (ICS.getKind()) {
49684976
case ImplicitConversionSequence::StandardConversion:
4969-
if (!CheckConvertedConstantConversions(*this, ICS.Standard))
4970-
return Diag(From->getLocStart(),
4971-
diag::err_typecheck_converted_constant_expression_disallowed)
4972-
<< From->getType() << From->getSourceRange() << T;
49734977
SCS = &ICS.Standard;
49744978
break;
49754979
case ImplicitConversionSequence::UserDefinedConversion:
4976-
// We are converting from class type to an integral or enumeration type, so
4977-
// the Before sequence must be trivial.
4978-
if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After))
4979-
return Diag(From->getLocStart(),
4980-
diag::err_typecheck_converted_constant_expression_disallowed)
4981-
<< From->getType() << From->getSourceRange() << T;
4980+
// We are converting to a non-class type, so the Before sequence
4981+
// must be trivial.
49824982
SCS = &ICS.UserDefined.After;
49834983
break;
49844984
case ImplicitConversionSequence::AmbiguousConversion:
49854985
case ImplicitConversionSequence::BadConversion:
4986-
if (!DiagnoseMultipleUserDefinedConversion(From, T))
4987-
return Diag(From->getLocStart(),
4988-
diag::err_typecheck_converted_constant_expression)
4989-
<< From->getType() << From->getSourceRange() << T;
4986+
if (!S.DiagnoseMultipleUserDefinedConversion(From, T))
4987+
return S.Diag(From->getLocStart(),
4988+
diag::err_typecheck_converted_constant_expression)
4989+
<< From->getType() << From->getSourceRange() << T;
49904990
return ExprError();
49914991

49924992
case ImplicitConversionSequence::EllipsisConversion:
49934993
llvm_unreachable("ellipsis conversion in converted constant expression");
49944994
}
49954995

4996-
ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting);
4996+
// Check that we would only use permitted conversions.
4997+
if (!CheckConvertedConstantConversions(S, *SCS)) {
4998+
return S.Diag(From->getLocStart(),
4999+
diag::err_typecheck_converted_constant_expression_disallowed)
5000+
<< From->getType() << From->getSourceRange() << T;
5001+
}
5002+
// [...] and where the reference binding (if any) binds directly.
5003+
if (SCS->ReferenceBinding && !SCS->DirectBinding) {
5004+
return S.Diag(From->getLocStart(),
5005+
diag::err_typecheck_converted_constant_expression_indirect)
5006+
<< From->getType() << From->getSourceRange() << T;
5007+
}
5008+
5009+
ExprResult Result =
5010+
S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting);
49975011
if (Result.isInvalid())
49985012
return Result;
49995013

50005014
// Check for a narrowing implicit conversion.
50015015
APValue PreNarrowingValue;
50025016
QualType PreNarrowingType;
5003-
switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue,
5017+
switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
50045018
PreNarrowingType)) {
50055019
case NK_Variable_Narrowing:
50065020
// Implicit conversion to a narrower type, and the value is not a constant
@@ -5009,13 +5023,13 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
50095023
break;
50105024

50115025
case NK_Constant_Narrowing:
5012-
Diag(From->getLocStart(), diag::ext_cce_narrowing)
5026+
S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
50135027
<< CCE << /*Constant*/1
5014-
<< PreNarrowingValue.getAsString(Context, PreNarrowingType) << T;
5028+
<< PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
50155029
break;
50165030

50175031
case NK_Type_Narrowing:
5018-
Diag(From->getLocStart(), diag::ext_cce_narrowing)
5032+
S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
50195033
<< CCE << /*Constant*/0 << From->getType() << T;
50205034
break;
50215035
}
@@ -5025,12 +5039,15 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
50255039
Expr::EvalResult Eval;
50265040
Eval.Diag = &Notes;
50275041

5028-
if (!Result.get()->EvaluateAsRValue(Eval, Context) || !Eval.Val.isInt()) {
5042+
if ((T->isReferenceType()
5043+
? !Result.get()->EvaluateAsLValue(Eval, S.Context)
5044+
: !Result.get()->EvaluateAsRValue(Eval, S.Context)) ||
5045+
(RequireInt && !Eval.Val.isInt())) {
50295046
// The expression can't be folded, so we can't keep it at this position in
50305047
// the AST.
50315048
Result = ExprError();
50325049
} else {
5033-
Value = Eval.Val.getInt();
5050+
Value = Eval.Val;
50345051

50355052
if (Notes.empty()) {
50365053
// It's a constant expression.
@@ -5041,16 +5058,34 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
50415058
// It's not a constant expression. Produce an appropriate diagnostic.
50425059
if (Notes.size() == 1 &&
50435060
Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
5044-
Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
5061+
S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
50455062
else {
5046-
Diag(From->getLocStart(), diag::err_expr_not_cce)
5063+
S.Diag(From->getLocStart(), diag::err_expr_not_cce)
50475064
<< CCE << From->getSourceRange();
50485065
for (unsigned I = 0; I < Notes.size(); ++I)
5049-
Diag(Notes[I].first, Notes[I].second);
5066+
S.Diag(Notes[I].first, Notes[I].second);
50505067
}
5051-
return Result;
5068+
return ExprError();
5069+
}
5070+
5071+
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
5072+
APValue &Value, CCEKind CCE) {
5073+
return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false);
5074+
}
5075+
5076+
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
5077+
llvm::APSInt &Value,
5078+
CCEKind CCE) {
5079+
assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
5080+
5081+
APValue V;
5082+
auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true);
5083+
if (!R.isInvalid())
5084+
Value = V.getInt();
5085+
return R;
50525086
}
50535087

5088+
50545089
/// dropPointerConversions - If the given standard conversion sequence
50555090
/// involves any pointer conversions, remove them. This may change
50565091
/// the result type of the conversion sequence.

0 commit comments

Comments
 (0)