On Wed, Nov 2, 2011 at 4:49 PM, Richard Trieu <[email protected]> wrote:
> On Wed, Nov 2, 2011 at 4:21 PM, Abramo Bagnara
> <[email protected]>wrote:
>
>> Il 03/11/2011 00:16, Richard Trieu ha scritto:
>> > On Wed, Nov 2, 2011 at 3:51 PM, Abramo Bagnara <
>> [email protected]
>> > <mailto:[email protected]>> wrote:
>> >
>> > Il 02/11/2011 03:21, Richard Trieu ha scritto:
>> > > On Mon, Oct 24, 2011 at 7:30 AM, Douglas Gregor <
>> [email protected]
>> > <mailto:[email protected]>
>> > > <mailto:[email protected] <mailto:[email protected]>>> wrote:
>> > >
>> > >
>> > > On Oct 20, 2011, at 5:36 PM, Chandler Carruth wrote:
>> > >
>> > >> On Thu, Oct 20, 2011 at 5:12 PM, Richard Trieu
>> > <[email protected] <mailto:[email protected]>
>> > >> <mailto:[email protected] <mailto:[email protected]>>>
>> wrote:
>> > >>
>> > >> Should Clang be printing suffixes that are accepted only
>> with
>> > >> certain flags?
>> > >>
>> > >>
>> > >> I think this is an interesting policy decision. I'd love to
>> hear
>> > >> Doug's thoughts on it.
>> > >>
>> > >> It seems fine to me for Clang, when running with
>> -fms-extensions,
>> > >> to suggest fixes even if only valid for -fms-extensions.
>> Clearly
>> > >> if there is a generic suggestion that could be made, that
>> > would be
>> > >> a preferred alternative. For example, '__asm__' should be
>> > >> suggested before 'asm'.
>> > >
>> > > I think it's fine for Clang to print suffixes that are only
>> > accepted
>> > > with certain flags. Presumably, you should never get an
>> > > IntegerLiteral of type __int128_t unless you're in a dialect
>> that
>> > > supports parsing it.
>> > >
>> > > … except that we cheat when we're building template arguments,
>> > > because it was convenient. That cheating could be eliminated
>> by
>> > > encoding integer literal values directly within
>> > > SubstNonTypeTemplateParmExpr.
>> > >
>> > > - Doug
>> > >
>> > >
>> > > New patch. Changes as follows:
>> > > Add int128 and uint128 suffixes (i128 and Ui128) to StmtPrinter.
>> > short
>> > > and unsigned short will get to llvm_unreachable
>> > > Add assert to IntergerLiteral to prevent creation with type short
>> or
>> > > unsigned short
>> > > Fix comment in IntegerLiteral to say that int128 and uint128 are
>> > > acceptable types
>> > > Change BuildExpressFromIntegralTemplateArgument to give a proper
>> Expr.
>> > > For negative numbers, use UnaryOperator of IntegerLiteral. For
>> short
>> > > and unsigned short, ImplicitCastExpr from int.
>> >
>> > Following this path have you considered how to represent an int
>> > parameter with value INT_MIN?
>> >
>> > I think there is no way you can represent it in standard conformant
>> way
>> > except to use -INT_MAX - 1 (i.e. -2147483647 <tel:2147483647> - 1
>> if
>> > int has 32 bits).
>> >
>> > You cannot use -214783648 because no integer literal of type int
>> with
>> > value 214783648 can exists.
>> >
>> >
>> > Richard Smith brought up a similar point in the code review comments. I
>> > am putting in an integer type selector which will move up to larger
>> > types until a large enough type can be found. For instance, for
>> > int_min, use the negation of a long with a cast back to int.
>>
>> What about when you don't have a larger type? (i.e. the minimum negative
>> number of larger signed integral type)
>>
>
> I'm thinking of switching to the unsigned version of that signed type.
> And if that is still not large enough, assert, because there's nothing
> left Clang can do.
>
Another patch. Have the integer type change to a larger type if the
current one isn't big enough. Signed and unsigned chars will be cast
integer literals instead of character literals. Moved the implicit cast to
be the outermost expression.
Index: test/Misc/integer-literal-printing.cpp
===================================================================
--- test/Misc/integer-literal-printing.cpp (revision 0)
+++ test/Misc/integer-literal-printing.cpp (revision 0)
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+// PR11179
+template <short T> class Type1 {};
+template <short T> void Function1(Type1<T>& x) {} // expected-note{{candidate function [with T = -42] not viable: no known conversion from 'Type1<-42>' to 'Type1<-42> &' for 1st argument;}}
+
+template <unsigned short T> class Type2 {};
+template <unsigned short T> void Function2(Type2<T>& x) {} // expected-note{{candidate function [with T = 42] not viable: no known conversion from 'Type2<42>' to 'Type2<42> &' for 1st argument;}}
+
+template <__int128_t T> class Type3 {};
+template <__int128_t T> void Function3(Type3<T>& x) {} // expected-note{{candidate function [with T = -42] not viable: no known conversion from 'Type3<-42>' to 'Type3<-42i128> &' for 1st argument;}}
+
+template <__uint128_t T> class Type4 {};
+template <__uint128_t T> void Function4(Type4<T>& x) {} // expected-note{{candidate function [with T = 42] not viable: no known conversion from 'Type4<42>' to 'Type4<42Ui128> &' for 1st argument;}}
+
+void Function() {
+ Function1(Type1<-42>()); // expected-error{{no matching function for call to 'Function1'}}
+ Function2(Type2<42>()); // expected-error{{no matching function for call to 'Function2'}}
+ Function3(Type3<-42>()); // expected-error{{no matching function for call to 'Function3'}}
+ Function4(Type4<42>()); // expected-error{{no matching function for call to 'Function4'}}
+}
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h (revision 142606)
+++ include/clang/AST/Expr.h (working copy)
@@ -1072,8 +1072,8 @@
: Expr(IntegerLiteralClass, Empty) { }
public:
- // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
- // or UnsignedLongLongTy
+ // type should be IntTy, LongTy, LongLongTy, Int128Ty, UnsignedIntTy,
+ // UnsignedLongTy, UnsignedLongLongTy, or UnsignedInt128Ty.
IntegerLiteral(ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l)
: Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
@@ -1082,6 +1082,9 @@
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
assert(V.getBitWidth() == C.getIntWidth(type) &&
"Integer type is not the correct size for constant.");
+ assert(!type->isSpecificBuiltinType(BuiltinType::Short) &&
+ !type->isSpecificBuiltinType(BuiltinType::UShort) &&
+ "Integer type cannot be short or unsigned short");
setValue(C, V);
}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp (revision 142606)
+++ lib/Sema/SemaTemplate.cpp (working copy)
@@ -4176,7 +4176,9 @@
assert(Arg.getKind() == TemplateArgument::Integral &&
"Operation is only valid for integral template arguments");
QualType T = Arg.getIntegralType();
- if (T->isAnyCharacterType()) {
+ if (T->isAnyCharacterType() &&
+ !T->isSpecificBuiltinType(BuiltinType::UChar) &&
+ !T->isSpecificBuiltinType(BuiltinType::SChar)) {
CharacterLiteral::CharacterKind Kind;
if (T->isWideCharType())
Kind = CharacterLiteral::Wide;
@@ -4199,7 +4201,41 @@
if (T->isNullPtrType())
return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
-
+
+ llvm::APInt Value = *Arg.getAsIntegral();
+ QualType OrigType;
+ bool IsNegative = Value.isNegative() && T->isSignedIntegerType();
+
+ // After this conversion, Value stores a positive value.
+ if (IsNegative && !Value.isMinSignedValue())
+ Value = Value.abs();
+
+ // Find the integer type that is large enough to fit the value.
+ if (T->isSpecificBuiltinType(BuiltinType::Short) ||
+ T->isSpecificBuiltinType(BuiltinType::UShort) ||
+ T->isSpecificBuiltinType(BuiltinType::SChar) ||
+ T->isSpecificBuiltinType(BuiltinType::UChar) ||
+ (Value.isMinSignedValue() && T->isSignedIntegerType())) {
+ OrigType = T;
+ unsigned BitWidth = Value.getBitWidth();
+ if (BitWidth < Context.getIntWidth(Context.IntTy))
+ T = Context.IntTy;
+ else if (BitWidth < Context.getIntWidth(Context.LongTy))
+ T = Context.LongTy;
+ else if (BitWidth < Context.getIntWidth(Context.LongLongTy))
+ T = Context.LongLongTy;
+ else if (BitWidth <= Context.getIntWidth(Context.UnsignedLongLongTy))
+ T = Context.UnsignedLongLongTy;
+ else if (BitWidth < Context.getIntWidth(Context.Int128Ty))
+ T = Context.Int128Ty;
+ else if (BitWidth <= Context.getIntWidth(Context.UnsignedInt128Ty))
+ T = Context.UnsignedInt128Ty;
+ else
+ llvm_unreachable("Integer size too large for built-in types.");
+
+ Value = Value.zext(Context.getIntWidth(T));
+ }
+
// If this is an enum type that we're instantiating, we need to use an integer
// type the same size as the enumerator. We don't want to build an
// IntegerLiteral with enum type.
@@ -4209,7 +4245,11 @@
else
BT = T;
- Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc);
+ Expr *E = IntegerLiteral::Create(Context, Value, BT, Loc);
+ if (IsNegative)
+ E = new (Context) UnaryOperator(E, UO_Minus, T, VK_RValue, OK_Ordinary,
+ Loc);
+
if (T->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
@@ -4217,7 +4257,14 @@
Context.getTrivialTypeSourceInfo(T, Loc),
Loc, Loc);
}
-
+
+ // If the integer literal was created with a different type, cast it back
+ // to the original type.
+ if (!OrigType.isNull()) {
+ E = ImplicitCastExpr::Create(Context, OrigType, CK_IntegralCast, E, 0,
+ VK_RValue);
+ }
+
return Owned(E);
}
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp (revision 142606)
+++ lib/AST/StmtPrinter.cpp (working copy)
@@ -665,6 +665,8 @@
case BuiltinType::ULong: OS << "UL"; break;
case BuiltinType::LongLong: OS << "LL"; break;
case BuiltinType::ULongLong: OS << "ULL"; break;
+ case BuiltinType::Int128: OS << "i128"; break;
+ case BuiltinType::UInt128: OS << "Ui128"; break;
}
}
void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits