diff --git a/decl.cpp b/decl.cpp index c7d048c7..04d19c39 100644 --- a/decl.cpp +++ b/decl.cpp @@ -55,14 +55,23 @@ lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) { return NULL; if ((typeQualifiers & TYPEQUAL_UNSIGNED) != 0) { + if ((typeQualifiers & TYPEQUAL_SIGNED) != 0) + Error(pos, "Illegal to apply both \"signed\" and \"unsigned\" " + "qualifiers."); + const Type *unsignedType = type->GetAsUnsignedType(); if (unsignedType != NULL) type = unsignedType; else Error(pos, "\"unsigned\" qualifier is illegal with \"%s\" type.", type->GetString().c_str()); + } + if ((typeQualifiers & TYPEQUAL_SIGNED) != 0 && type->IsIntType() == false) + Error(pos, "\"signed\" qualifier is illegal with non-integer type " + "\"%s\".", type->GetString().c_str()); + if ((typeQualifiers & TYPEQUAL_CONST) != 0) type = type->GetAsConstType(); @@ -138,6 +147,7 @@ DeclSpecs::Print() const { if (typeQualifiers & TYPEQUAL_UNIFORM) printf("uniform "); if (typeQualifiers & TYPEQUAL_VARYING) printf("varying "); if (typeQualifiers & TYPEQUAL_TASK) printf("task "); + if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed "); if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned "); printf("%s", baseType->GetString().c_str()); diff --git a/decl.h b/decl.h index de966f41..cd6f34b8 100644 --- a/decl.h +++ b/decl.h @@ -79,8 +79,9 @@ enum StorageClass { #define TYPEQUAL_UNIFORM (1<<1) #define TYPEQUAL_VARYING (1<<2) #define TYPEQUAL_TASK (1<<3) -#define TYPEQUAL_UNSIGNED (1<<4) -#define TYPEQUAL_INLINE (1<<5) +#define TYPEQUAL_SIGNED (1<<4) +#define TYPEQUAL_UNSIGNED (1<<5) +#define TYPEQUAL_INLINE (1<<6) /** @brief Representation of the declaration specifiers in a declaration. diff --git a/lex.ll b/lex.ll index c8ff9b1d..4ee811b3 100644 --- a/lex.ll +++ b/lex.ll @@ -117,6 +117,7 @@ reference { Error(*yylloc, "\"reference\" qualifier is no longer supported; " "instead."); } return { return TOKEN_RETURN; } soa { return TOKEN_SOA; } +signed { return TOKEN_SIGNED; } sizeof { return TOKEN_SIZEOF; } static { return TOKEN_STATIC; } struct { return TOKEN_STRUCT; } diff --git a/parse.yy b/parse.yy index 2d62d4d8..540437af 100644 --- a/parse.yy +++ b/parse.yy @@ -106,14 +106,14 @@ static const char *lBuiltinTokens[] = { "cif", "cwhile", "const", "continue", "creturn", "default", "do", "double", "else", "enum", "export", "extern", "false", "float", "for", "goto", "if", "inline", "int", "int8", "int16", "int32", "int64", "launch", "NULL", - "print", "return", "sizeof", + "print", "return", "signed", "sizeof", "static", "struct", "switch", "sync", "task", "true", "typedef", "uniform", "unsigned", "varying", "void", "while", NULL }; static const char *lParamListTokens[] = { "bool", "const", "double", "enum", "false", "float", "int", - "int8", "int16", "int32", "int64", "struct", "true", + "int8", "int16", "int32", "int64", "signed", "struct", "true", "uniform", "unsigned", "varying", "void", NULL }; @@ -158,7 +158,7 @@ static const char *lParamListTokens[] = { %token TOKEN_EXTERN TOKEN_EXPORT TOKEN_STATIC TOKEN_INLINE TOKEN_TASK %token TOKEN_UNIFORM TOKEN_VARYING TOKEN_TYPEDEF TOKEN_SOA -%token TOKEN_CHAR TOKEN_INT TOKEN_UNSIGNED TOKEN_FLOAT TOKEN_DOUBLE +%token TOKEN_CHAR TOKEN_INT TOKEN_SIGNED TOKEN_UNSIGNED TOKEN_FLOAT TOKEN_DOUBLE %token TOKEN_INT8 TOKEN_INT16 TOKEN_INT64 TOKEN_CONST TOKEN_VOID TOKEN_BOOL %token TOKEN_ENUM TOKEN_STRUCT TOKEN_TRUE TOKEN_FALSE @@ -724,6 +724,13 @@ specifier_qualifier_list $$ = $2->GetAsVaryingType(); else if ($1 == TYPEQUAL_CONST) $$ = $2->GetAsConstType(); + else if ($1 == TYPEQUAL_SIGNED) { + if ($2->IsIntType() == false) { + Error(@1, "Can't apply \"signed\" qualifier to \"%s\" type.", + $2->GetString().c_str()); + $$ = $2; + } + } else if ($1 == TYPEQUAL_UNSIGNED) { const Type *t = $2->GetAsUnsignedType(); if (t) @@ -865,6 +872,7 @@ type_qualifier | TOKEN_VARYING { $$ = TYPEQUAL_VARYING; } | TOKEN_TASK { $$ = TYPEQUAL_TASK; } | TOKEN_INLINE { $$ = TYPEQUAL_INLINE; } + | TOKEN_SIGNED { $$ = TYPEQUAL_SIGNED; } | TOKEN_UNSIGNED { $$ = TYPEQUAL_UNSIGNED; } ; diff --git a/tests_errors/signed-float-1.ispc b/tests_errors/signed-float-1.ispc new file mode 100644 index 00000000..ec2a7220 --- /dev/null +++ b/tests_errors/signed-float-1.ispc @@ -0,0 +1,5 @@ +// Can't apply "signed" qualifier to "float" type + +struct Foo { + signed float x; +}; diff --git a/tests_errors/signed-float.ispc b/tests_errors/signed-float.ispc new file mode 100644 index 00000000..418cd8db --- /dev/null +++ b/tests_errors/signed-float.ispc @@ -0,0 +1,5 @@ +// "signed" qualifier is illegal with non-integer type "float" + +int foo() { + signed float x; +} diff --git a/tests_errors/signed-struct.ispc b/tests_errors/signed-struct.ispc new file mode 100644 index 00000000..4171c518 --- /dev/null +++ b/tests_errors/signed-struct.ispc @@ -0,0 +1,7 @@ +// "signed" qualifier is illegal with non-integer type "uniform struct Foo" + +struct Foo { + float x; +}; + +signed Foo f; diff --git a/tests_errors/signed-unsigned.ispc b/tests_errors/signed-unsigned.ispc new file mode 100644 index 00000000..c9da58f0 --- /dev/null +++ b/tests_errors/signed-unsigned.ispc @@ -0,0 +1,5 @@ +// Error: Illegal to apply both "signed" and "unsigned" qualifiers + +int foo() { + signed unsigned int x; +} diff --git a/tests_errors/unsigned-float-1.ispc b/tests_errors/unsigned-float-1.ispc new file mode 100644 index 00000000..2975c800 --- /dev/null +++ b/tests_errors/unsigned-float-1.ispc @@ -0,0 +1,5 @@ +// Can't apply "unsigned" qualifier to "float" type + +struct Foo { + unsigned float x; +}; diff --git a/tests_errors/unsigned-struct.ispc b/tests_errors/unsigned-struct.ispc new file mode 100644 index 00000000..107a988b --- /dev/null +++ b/tests_errors/unsigned-struct.ispc @@ -0,0 +1,7 @@ +// "unsigned" qualifier is illegal with "uniform struct Foo" typ + +struct Foo { + float x; +}; + +unsigned Foo f;