diff --git a/Parser.pas b/Parser.pas index f1a5a39..834ebfa 100644 --- a/Parser.pas +++ b/Parser.pas @@ -3139,12 +3139,18 @@ while token.kind in allowedTokens do begin if doingForLoopClause1 then if not (myStorageClass in [autosy,registersy]) then Error(127); + if _Thread_localsy in myDeclarationModifiers then + if not (myStorageClass in [staticsy,externsy]) then + Error(177); NextToken; end; _Thread_localsy: begin myDeclarationModifiers := myDeclarationModifiers + [token.kind]; - Error(139); + if doingParameters then + Error(87); + if not (myStorageClass in [ident,staticsy,externsy]) then + Error(177); NextToken; end; @@ -3464,6 +3470,10 @@ while token.kind in allowedTokens do begin isForwardDeclared := myIsForwardDeclared; skipDeclarator := mySkipDeclarator; declSpecifiers.declarationModifiers := myDeclarationModifiers; +if _Thread_localsy in myDeclarationModifiers then + if myStorageClass = ident then + if doingFunction then + Error(177); if myTypeSpec = nil then begin myTypeSpec := intPtr; {under C89, default type is int} if (lint & lintC99Syntax) <> 0 then @@ -3780,6 +3790,8 @@ if isFunction then begin Error(120); if alignmentSpecified then Error(142); + if _Thread_localsy in declSpecifiers.declarationModifiers then + Error(178); if isPascal then begin {reverse prototyped parameters} p1 := fnType^.parameterList; if p1 <> nil then begin diff --git a/Scanner.pas b/Scanner.pas index e26e1b9..3cb93f9 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -715,7 +715,7 @@ if list or (numErr <> 0) then begin 136: msg := @'complex or imaginary types are not supported by ORCA/C'; 137: msg := @'atomic types are not supported by ORCA/C'; 138: msg := @'unsupported alignment'; - 139: msg := @'thread-local storage is not supported by ORCA/C'; + {139: msg := @'thread-local storage is not supported by ORCA/C';} 140: msg := @'unexpected token'; 141: msg := @'_Noreturn specifier is only allowed on functions'; 142: msg := @'_Alignas may not be used in this declaration or type name'; @@ -753,6 +753,8 @@ if list or (numErr <> 0) then begin 174: msg := @'''__VA_ARGS__'' may only be used in a variadic macro'; 175: msg := @'duplicate macro parameter name'; 176: msg := @'declarator expected'; + 177: msg := @'_Thread_local may not be used with the specified storage class'; + 178: msg := @'_Thread_local may not appear in a function declaration'; otherwise: Error(57); end; {case} writeln(msg^); diff --git a/Tests/Conformance/DOIT3 b/Tests/Conformance/DOIT3 index 4b3bb84..9ef8946 100644 --- a/Tests/Conformance/DOIT3 +++ b/Tests/Conformance/DOIT3 @@ -31,3 +31,4 @@ {1} c11uchar.c {1} c11ternary.c {1} c11anonsu.c +{1} c11thrdlcl.c diff --git a/Tests/Conformance/c11thrdlcl.c b/Tests/Conformance/c11thrdlcl.c new file mode 100644 index 0000000..cb995f0 --- /dev/null +++ b/Tests/Conformance/c11thrdlcl.c @@ -0,0 +1,29 @@ +/* + * Test _Thread_local (C11). + */ + +#include + +extern _Thread_local int i; +char static _Thread_local c = 5; +_Thread_local struct {int x,y,z;} s = {3,6,8}; + +int main(void) { + _Thread_local int extern j; + static _Thread_local long d = 4567; + + d = 123; + i = 14; + + if (i+j+c+d+s.x+s.y+s.z != 171) + goto Fail; + + printf ("Passed Conformance Test c11thrdlcl\n"); + return 0; + +Fail: + printf ("Failed Conformance Test c11thrdlcl\n"); +} + +int _Thread_local i = 9999; +_Thread_local int j = 12; diff --git a/cc.notes b/cc.notes index 2bb493b..d19b44a 100644 --- a/cc.notes +++ b/cc.notes @@ -426,7 +426,7 @@ ORCA/C 2.2.0 adds support for several new C language features. Most are feature restrict inline (already treated as a keyword by ORCA/C) -Of these, _Atomic, _Complex, _Imaginary, and _Thread_local are recognized as keywords, but the corresponding language features are not yet supported, so any attempt to use them will produce an error message. The other new keywords are supported, as described below. +Of these, _Atomic, _Complex, and _Imaginary are recognized as keywords, but the corresponding language features are not supported, so any attempt to use them will produce an error message. The other new keywords are supported, as described below. 2. (C99) Statements and declarations may now be mixed within a block; declarations are no longer required to come before statements. The first clause of a for loop statement may also be a declaration (with auto or register storage class only). Variables may only be referred to by name in code syntactically after their declaration, but their lifetime continues as long as control remains in the enclosing block scope, even if it returns to a point before the declaration. Initializers for variables with automatic storage duration are evaluated whenever execution reaches the point where they appear in the code. @@ -579,6 +579,10 @@ Here is an example of a structure containing an anonymous union that in turn con Members of anonymous structures or unions (including nested ones) may be accessed as if they are members of the containing structure or union. For example, given the declaration above, the expressions s.a, s.b, s.c, and s.d may be used to access the various fields. All the fields must have distinct names. +28. (C11) ORCA/C can now accept the _Thread_local storage-class specifier, which indicates that a variable has thread-local storage. On platforms that support multithreading, there would be a separate copy of the variable for each running thread in the program. ORCA/C does not support multithreading, so the whole execution of an ORCA/C program consists of a single thread, and therefore there is only one copy of each thread-local variable. Accordingly, the _Thread_local storage-class specifier is essentially ignored by ORCA/C, but it may be used in portable code designed to support multithreading on other systems. + +The _Thread_local storage-class specifier may be used together with static or extern. This has the normal effect of the other storage-class specifier while also indicating that the variable has thread-local storage. For declarations within a function, _Thread_local must be used together with static or extern. + Multi-Character Character Constants -----------------------------------