diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 16 | ||||
-rw-r--r-- | clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp | 14 |
2 files changed, 25 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 994471ab5c5..d723d45587f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -389,11 +389,20 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, const unsigned ToWidth = Ctx.getIntWidth(ToType); if (FromWidth > ToWidth || - (FromWidth == ToWidth && FromSigned != ToSigned)) { + (FromWidth == ToWidth && FromSigned != ToSigned) || + (FromSigned && !ToSigned)) { // Not all values of FromType can be represented in ToType. llvm::APSInt InitializerValue; const Expr *Initializer = IgnoreNarrowingConversion(Converted); - if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { + if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { + // Such conversions on variables are always narrowing. + return NK_Variable_Narrowing; + } else if (FromWidth < ToWidth) { + // Negative -> unsigned is narrowing. Otherwise, more bits is never + // narrowing. + if (InitializerValue.isSigned() && InitializerValue.isNegative()) + return NK_Constant_Narrowing; + } else { ConstantValue = APValue(InitializerValue); // Add a bit to the InitializerValue so we don't have to worry about @@ -411,9 +420,6 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, ConstantType = Initializer->getType(); return NK_Constant_Narrowing; } - } else { - // Variables are always narrowings. - return NK_Variable_Narrowing; } } return NK_Not_Narrowing; diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp index db20ea6426e..e3909cce13b 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp @@ -167,6 +167,20 @@ void shrink_int() { Agg<short> ce1 = { Convert<int>(100000) }; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} expected-note {{override}} expected-warning {{changes value from 100000 to -31072}} Agg<char> ce2 = { ConvertVar<short>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'short' to 'char'}} expected-note {{override}} + + // Negative -> larger unsigned type. + unsigned long long ll1 = { -1 }; // expected-error {{cannot be narrowed}} expected-note {{override}} + unsigned long long ll2 = { 1 }; // OK + unsigned long long ll3 = { s }; // expected-error {{cannot be narrowed}} expected-note {{override}} + unsigned long long ll4 = { us }; // OK + unsigned long long ll5 = { ll }; // expected-error {{cannot be narrowed}} expected-note {{override}} + Agg<unsigned long long> ll6 = { -1 }; // expected-error {{cannot be narrowed}} expected-note {{override}} + Agg<unsigned long long> ll7 = { 18446744073709551615ULL }; // OK + Agg<unsigned long long> ll8 = { __int128(18446744073709551615ULL) + 1 }; // expected-error {{cannot be narrowed}} expected-note {{override}} expected-warning {{changes value}} + signed char c = 'x'; + unsigned short usc1 = { c }; // expected-error {{cannot be narrowed}} expected-note {{override}} + unsigned short usc2 = { (signed char)'x' }; // OK + unsigned short usc3 = { (signed char)-1 }; // expected-error {{cannot be narrowed}} expected-note {{override}} } // Be sure that type- and value-dependent expressions in templates get the error |