Jump to content
Connie McBride

Error : constant expression violates subrange bounds

Recommended Posts

Using Delphi 12,  upgrading from Delphi11, using windows 32 as target.

 

when building, I am getting this error:

 

[dcc32 Errorr E1012 Constant expression violates subrange bounds

the errror is in Winapi.Windows

 

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = Integer($80000000);

 

any ideas how to fix this?

Share this post


Link to post

Question: Why are you compiling Winapi.Windows.pas in the first place?

  • Like 2

Share this post


Link to post
4 minutes ago, Connie McBride said:

I'm actually not.

one of my .pas files is using CW_USEDEFAULT, which is leading to the compile error.

 

 

Mat be you are using it with UINT32 parameter or something like that ?

Share this post


Link to post
43 minutes ago, Connie McBride said:

I'm actually not.

one of my .pas files is using CW_USEDEFAULT, which is leading to the compile error.

 

 

Then you seem to have Winapi.Windows.pas in your search path. Otherwise the compiler won't try to compile that issuing that error.

Share this post


Link to post

I am building the crystal 13 vcl components for delphi 12.

I don't have rtl in my search path

image.png.cd44c22a6bc4ef1c67f53e8bb0b7829b.png

Ucrpe.pas is failing on this line :

 

function TCrpe.SendOutput : Boolean;
var
  nLeft, nTop,
  nWidth, nHeight : DWord;
  xHandle         : hWnd;
begin

....

        if FWindowSize.FLeft = -1 then
          nLeft := CW_USEDEFAULT  <<<<<<HERE 

 

nLeft is defined as DWord.

 

 

so the .pas isn't in my search path, it's the same code that has worked in delphi 10 up to delphi 11.3.

 


 

Share this post


Link to post
7 hours ago, Connie McBride said:

function TCrpe.SendOutput : Boolean;
var
  nLeft, nTop,
  nWidth, nHeight : DWord;
  xHandle         : hWnd;
begin

....

        if FWindowSize.FLeft = -1 then
          nLeft := CW_USEDEFAULT  <<<<<<HERE 

 

nLeft is defined as DWord.

 

 

Share this post


Link to post

This was changed in D12, in Delphi 11 it was declared as:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = DWORD($80000000);

 

now it's:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = Integer($80000000);
 

 

 

  • Like 1

Share this post


Link to post
7 hours ago, Lajos Juhász said:

This was changed in D12, in Delphi 11 it was declared as:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = DWORD($80000000);

 

now it's:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = Integer($80000000);

Which makes sense, as that flag is used primarily with the CreateWindow/Ex() APIs and they accept it as an int, not a dword.

Share this post


Link to post
7 hours ago, Lajos Juhász said:

This was changed in D12, in Delphi 11 it was declared as:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = DWORD($80000000);

 

now it's:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = Integer($80000000);
 

 

 

I changed the variable in the code to be an integer vs a dword, and now it works.

but heads up to anyone who runs into this.

Share this post


Link to post
2 minutes ago, Connie McBride said:

I changed the variable in the code to be an integer vs a dword

Why were your variables declared as DWORD to begin with?  The Win32 API represents window positions and sizes as ints, not as dwords.

Share this post


Link to post
31 minutes ago, Remy Lebeau said:

Why were your variables declared as DWORD to begin with?  The Win32 API represents window positions and sizes as ints, not as dwords.

May be this is the cause:

 

8 hours ago, Lajos Juhász said:

This was changed in D12, in Delphi 11 it was declared as:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = DWORD($80000000);

  

now it's:

const
  {$EXTERNALSYM CW_USEDEFAULT}
  CW_USEDEFAULT = Integer($80000000);
 

 

 

 

Share this post


Link to post
1 hour ago, DelphiUdIT said:

May be this is the cause:

I was referring to this code:

18 hours ago, Connie McBride said:

Ucrpe.pas is failing on this line :

 

function TCrpe.SendOutput : Boolean;
var
  nLeft, nTop,
  nWidth, nHeight : DWord;
  xHandle         : hWnd;
begin

....

        if FWindowSize.FLeft = -1 then
          nLeft := CW_USEDEFAULT  <<<<<<HERE 

 

nLeft is defined as DWord.

Why were nLeft, etc declared as DWord to begin with and not as Integer, as the Win32 API expects?

Edited by Remy Lebeau

Share this post


Link to post
3 minutes ago, Remy Lebeau said:

I was referring to this code:

Why were nLeft, etc declared as DWord to begin with and not as Integer, as the Win32 API expects?

because the library was built to run in delphi11, where cw_usedefault was defined as a dword. 

that constant changed in delphi12, where it is now an integer

 

Share this post


Link to post
22 minutes ago, Connie McBride said:

because the library was built to run in delphi11, where cw_usedefault was defined as a dword. 

that constant changed in delphi12, where it is now an integer

IMHO, just because the constant was DWord doesn't mean the variables should have been DWord.

  • Like 1

Share this post


Link to post
14 hours ago, Remy Lebeau said:

IMHO, just because the constant was DWord doesn't mean the variables should have been DWord.

This inconsistency is very annoying with Delphi compiler, and as you see it, untyped constant should be ... well .... untyped , duh ! , its value i mean in this case numerical value used as needed and casted in place of usage.

 

In this piece the compiler refuse to handle "HandleDWORD(A)" for no logical reason, notice it doesn't have problem with the more dangerous one "HandleInteger(B)"

const
  A = Integer($80000000);
  B = DWORD($80000000);
  C = $80000000;
  D = MINLONG;

procedure HandleInteger(Value:Integer);
begin
  Writeln(Value);
end;

procedure HandleDWORD(Value:DWORD);
begin
  Writeln(Value);
end;

begin
  HandleInteger(A);
  HandleInteger(B);
  HandleInteger(C);
  HandleInteger(D);

  //HandleDWORD(A);    // [dcc32 Error] Project5.dpr(36): E1012 Constant expression violates subrange bounds
  HandleDWORD(B);
  HandleDWORD(C);
  HandleDWORD(D);

  Readln;
end.

Result on my XE8

Quote

-2147483648
-2147483648
-2147483648
-2147483648
2147483648
2147483648
2147483648

I wonder what is the result with Delphi 12 ?! considering there is a change did broke untyped constant handling.

Share this post


Link to post
37 minutes ago, Kas Ob. said:

This inconsistency is very annoying with Delphi compiler, and as you see it, untyped constant should be ... well .... untyped , duh ! , its value i mean in this case numerical value used as needed and casted in place of usage.

Uhmm, I think there are good... actually very good reasons why "errors" are generated (AND SHOULD BE) in "Integer and Unsigned Integer" cases and the like.
The first and most trivial case is the comparison operation. Comparing (or assigning) integers and unsigned integers is a huge mistake (i.e. it happens in the example from which the topic was generated).

I think this is enough to define that there cannot be operations with "automatic" type conversion in these cases.

Forcing the operation (therefore through typecasting) is the path that should be followed: the programmer knows what he is doing and solves the problem by forcing the operation.

Already the definition of "-1" could create some "stomach ache" (it is an Italian way of saying that it creates "discomfort"). Those who programmed in assembler certainly remember the old Intel CWD-type instructions...

 

1 hour ago, Kas Ob. said:

In this piece the compiler refuse to handle "HandleDWORD(A)" for no logical reason, notice it doesn't have problem with the more dangerous one "HandleInteger(B)"

Result on my XE8

I wonder what is the result with Delphi 12 ?! considering there is a change did broke untyped constant handling.

A runtime, in Delphi 12 an Error was generated at the second instruction (like you told, "more dangerous") only in Debug mode ('Range check error'), but during compilation many warnings are generated regarding its use. Maybe the Warnings are not enough, they should be switched to error...

 

HandleInteger(B);

It is for this reason that it should not be allowed to carry out automatic conversions, already at the compiler level.

I use and love Delphi, among other things, because when you write code and compile it you have a good certainty (I said "good" not "sure") that the code will run error-free, at least for basic errors.

 

Share this post


Link to post

Sorry, I can't agree on the rightness of this, heck.. i might call it rightmess !

 

Is Delphi 12 compiler handling (and generating machine code for) untyped numerical constant (literal) to be evaluated at runtime ?

That is wrong.

 

52 minutes ago, DelphiUdIT said:

but during compilation many warnings are generated regarding its use.

It would be great if you or anyone shared these warnings, i only can imagine what could be the case(s), but still when and where the compiler draw the line for such runtime evaluations yet it does accept them at compile time ?

 

Also on side note how the compiler will handle such constants without a type when used in 64bit (Int64 and UInt64) ?

 

See, the idea of being typed by a modifier after the "=" for numerical constant is disturbing me.

Share this post


Link to post
43 minutes ago, Kas Ob. said:

It would be great if you or anyone shared these warnings, i only can imagine what could be the case(s), but still when and where the compiler draw the line for such runtime evaluations yet it does accept them at compile time

image.thumb.png.adfea315a379d8a8af99d64da0c37da9.png

 

Edited by DelphiUdIT
  • Thanks 1

Share this post


Link to post
9 hours ago, Kas Ob. said:

This inconsistency is very annoying with Delphi compiler, and as you see it, untyped constant should be ... well .... untyped , duh ! , its value i mean in this case numerical value used as needed and casted in place of usage.

CW_USEDEFAULT is actually typed as 'int' in the Windows SDK (in winuser.h):

#define CW_USEDEFAULT       ((int)0x80000000)

 

Share this post


Link to post
12 hours ago, Remy Lebeau said:

CW_USEDEFAULT is actually typed as 'int' in the Windows SDK (in winuser.h):

Right.

 

Microsoft define its literals strictly in most cases, yet the compiler has well defined behavior, both for the best outcome from using the SDK.

Look at this

image.thumb.png.d7c99d0951cc8026774f1c9c48287d1c.png

no problem and no warning.

 

Here the compiler warns but compile, and the IDE didn't show anything different for the other DWORD and INT32

image.thumb.png.4036d61c07fcfc4ed698d3e9ee4af079.png

 

But here with lets say HANDLE

image.thumb.png.f90861d3738f4eb01412723e49effc0a.png

Things are very different, as HANDLE are defined as struct as you know, specially to prevent the code from doing constant assignment. 

Like this

image.thumb.png.ac17c3442c53c2a75f7d9e7ac04cb575.png

 

Now why it is an integer: i think because it had been misunderstood as very big value (not the biggest though 0x80000000) instead of lowest possible negative value in 32bit, it could simply been declared as -1 and called a day, but who knows might be some legacy issue.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×