Skip to content

What's new

Y-Less edited this page Mar 31, 2019 · 41 revisions

Table of Contents

Bug fixes

See Known compiler bugs for the full list of known bugs and their current status.

Features

Preprocessor directives

#pragma compat

Toggles compatibility mode on or off.

Note: this pragma will not change the value of __Pawn.

#pragma naked

Suppress the "must return a value" warning for a function.

This can be used on functions that don't have a return statement but still return a value, e.g. via #emit retn.

#pragma warning

This directive comes in two forms:

  • #pragma warning (enable|disable) XXX

Enable or disable a warning by its number.

Useful for hiding unwanted warnings that otherwise cannot be fixed.

  • #pragma warning (push|pop)

Save or restore the list of currently disabled warnings.

This can be used in conjuction with the previous form to toggle warnings for a piece of code:

#pragma warning push
#pragma warning disable XXX

// some code here
...

#pragma warning pop

#warning

Print a user warning.

This works similar to the #error directive. For example, compiling a file that contains

#warning Don't include this file

would result in

warning 237: user warning: Don't include this file

#pragma option

Using #pragma option you can pass command line options to the compiler. Examples:

#pragma option -(+
#pragma option -l
#pragma option -E

Built-in constants

__line

The built-in __line constant is set to the current line number.

Backported from Pawn 4.0.

__file

__file is always set to the name of the current source code file.

__date

Current date. Example: 05 Feb 2017.

__time

Current time in 24-hour format. Example: 13:05:24.

This is the time when the compiler started executing. It doesn't change during compilation, no matter how long it takes.

__compat

Set to 0 (zero) if compatibility mode is disabled and any non-zero value otherwise.

__PawnBuild

Compiler build number. For example, for compiler version 3.10.123 this is the 123 part.

#if __Pawn >= 0x030A && __PawnBuild >= 2
    #define CURRENT_FILE __file
#else
    #define CURRENT_FILE ""
#end

Other features

Enums and sizeof in default arguments

If you have an enum where one of the members (fields) is an array:

enum Foo {
    a,
    b[10]
};

new bar[100][Foo];

and you use it in a function that has a parameter with a default value equal to sizeof(other_parameter), for instance:

f(x[], size = sizeof(x)) {
    #pragma unused x
    printf("size = %d", size); // size = 10
}

main() {
    f(bar[0][b]);
}

the size parameter would be set to the size of b, i.e. 10 cells, as opposed to 1 cell like with the old compiler.

Some might argue that sizeof should return 1 in such cases, since enums are not real structures but just numbers, and x[0][b] refers to a single cell, but that is rather counter-intuitive and may lead to hard to find mistakes, such as in this code:

strcat(x[b], "some string");

Backported from Pawn 3.3.4058.

Progressive initializers for 2d arrays

Initialization of two-dimensional arrays can be continued with an ellipsis operator, similar to one-dimensional arrays. For example, the following code:

new a[5][10] = {{0, 1, 2, ...}, {0, 2, 4, ...}, ...};

is equivalent to:

new a[5][10] = {
    {0, 1, 2,  3,  4,  5,  6,  7,  8,  9},
    {0, 2, 4,  6,  8,  10, 12, 14, 16, 18},
    {0, 3, 6,  9,  12, 15, 18, 21, 24, 27},
    {0, 4, 8,  12, 16, 20, 24, 28, 32, 36},
    {0, 5, 10, 15, 20, 25, 30, 35, 40, 45}
};

4d arrays

It is possible to define arrays with 4 dimensions:

new a[2][3][4][5] = { /* ... */ };

__emit operator

In addition to the #emit preprocessor directive there is a new __emit operator that has a similar purpose but has a few advantages. For example, it can be used inside expressions or macros. See this comment for the full comparison.

Treat warnings as errors

There is a new command line switch -E that tells the compiler to treat any warnings as errors. That is, things that would normally only cause a warning will become compile errors when this option is enabled.

Breaking changes

The following changes may break existing code:

No automatic #include guards

The automatic generation of _inc_XXX symbols was disabled due to their inconsistent behavior across platforms (Linux vs. Windows). See #6 for details.

In order to make it possible to include the same file multiple times without getting compile errors you can add something like this to your include file:

#if defined YOUR_INCLUDE_INC
  #endinput
#endif
#define YOUR_INCLUDE_INC

// code goes here

The old behaviour can be restored with Compatibility Mode

New __Pawn value

The value of the built-in __Pawn constant was changed from 0x0302 to 0x030A (#5). This allows you to do detect this compiler at compile time:

#if __Pawn == 0x030A
  // some code here
#else
  // alternative code
#endif

const correctness

const-correctness is checking that arguments to functions (mostly arrays) are const when they should be and not when they shouldn't. The old compiler had a basic version of this - you could not pass an explicitly declared const array to a non-const function:

Target(arr[])
{
}

Source(const arr[])
{
    Target(arr); // Error.
}

This is an error because you are trying to pass something that can't be modified (that's what const means) to a function that might modify it - because the parameter is not marked const. Basically, you can't remove const from an array.

As of 3.10.9, several other versions of constantness have been enforced (they were always in the compiler, but commented out):

  1. String literals are const by default. They are not variables you can write to, but literally a constant value. Thus this is no longer valid:
Target(arr[])
{
}

Source()
{
    Target("Hello"); // This is a constant string, it can't be passed to `Target`.
}

In both the above examples, the solution is to make arr const in Target:

Target(const arr[])
{
}
  1. If a function takes a non-const array, but doesn't modify it, it could be made const and the compiler will give a warning stating this:
Target(arr[])
{
    print(arr);
}

arr is only read, not written, so it should be const.