-
-
Notifications
You must be signed in to change notification settings - Fork 672
fix Issue 17425 - add __traits(getParameterStorageClasses, f, i) #6829
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| add __traits(getParameterStorageClasses, f, i) | ||
|
|
||
| $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17425, Bugzilla 17425) | ||
|
|
||
| --- | ||
| ref int foo(return ref const int* p, scope int* a, out int b, lazy int c); | ||
|
|
||
| pragma(msg, __traits(getParameterStorageClasses, foo, 0)); | ||
|
|
||
| static assert(__traits(getParameterStorageClasses, foo, 0)[0] == "return"); | ||
| static assert(__traits(getParameterStorageClasses, foo, 0)[1] == "ref"); | ||
|
|
||
| pragma(msg, __traits(getParameterStorageClasses, foo, 1)); | ||
| static assert(__traits(getParameterStorageClasses, foo, 1)[0] == "scope"); | ||
| static assert(__traits(getParameterStorageClasses, foo, 2)[0] == "out"); | ||
| static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy"); | ||
| --- | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,6 +97,7 @@ static this() | |
| "getAttributes", | ||
| "getFunctionAttributes", | ||
| "getFunctionVariadicStyle", | ||
| "getParameterStorageClasses", | ||
| "getUnitTests", | ||
| "getVirtualIndex", | ||
| "getPointerBitmap", | ||
|
|
@@ -968,6 +969,109 @@ extern (C++) Expression semanticTraits(TraitsExp e, Scope* sc) | |
| auto se = new StringExp(e.loc, cast(char*)style); | ||
| return se.semantic(sc); | ||
| } | ||
| if (e.ident == Id.getParameterStorageClasses) | ||
| { | ||
| /* Accept a function symbol or a type, followed by a parameter index. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about putting this code into a function? This improves readable and avoids making this function even larger (dmd is rather slow optimizing large functions).
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I leave refactorings to subsequent PRs, because they distract from what is being changed here. |
||
| * Returns a tuple of strings of the parameter's storage classes. | ||
| */ | ||
| // get symbol linkage as a string | ||
| if (dim != 2) | ||
| return dimError(2); | ||
|
|
||
| auto o1 = (*e.args)[1]; | ||
| auto o = (*e.args)[0]; | ||
| auto t = isType(o); | ||
| TypeFunction tf = null; | ||
| if (t) | ||
| { | ||
| if (t.ty == Tfunction) | ||
| tf = cast(TypeFunction)t; | ||
| else if (t.ty == Tdelegate) | ||
| tf = cast(TypeFunction)t.nextOf(); | ||
| else if (t.ty == Tpointer && t.nextOf().ty == Tfunction) | ||
| tf = cast(TypeFunction)t.nextOf(); | ||
| } | ||
| Parameters* fparams; | ||
| if (tf) | ||
| { | ||
| fparams = tf.parameters; | ||
| } | ||
| else | ||
| { | ||
| auto s = getDsymbol(o); | ||
| FuncDeclaration fd; | ||
| if (!s || (fd = s.isFuncDeclaration()) is null) | ||
| { | ||
| e.error("first argument to `__traits(getParameterStorageClasses, %s, %s)` is not a function", | ||
| o.toChars(), o1.toChars()); | ||
| return new ErrorExp(); | ||
| } | ||
| fparams = fd.getParameters(null); | ||
| } | ||
|
|
||
| StorageClass stc; | ||
|
|
||
| // Set stc to storage class of the ith parameter | ||
| auto ex = isExpression((*e.args)[1]); | ||
| if (!ex) | ||
| { | ||
| e.error("expression expected as second argument of `__traits(getParameterStorageClasses, %s, %s)`", | ||
| o.toChars(), o1.toChars()); | ||
| return new ErrorExp(); | ||
| } | ||
| ex = ex.ctfeInterpret(); | ||
| auto ii = ex.toUInteger(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't propagate errors if the expression does not evaluate to an integer. That is not checked in other uses of toInteger/toUInteger elsewhere, too, though. Maybe add test
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a generic problem with all those functions, and fixing them should be in a separate PR. |
||
| if (ii >= fparams.dim) | ||
| { | ||
| e.error("parameter index must be in range 0..%u not %s", cast(uint)fparams.dim, ex.toChars()); | ||
| return new ErrorExp(); | ||
| } | ||
|
|
||
| uint n = cast(uint)ii; | ||
| Parameter p = Parameter.getNth(fparams, n); | ||
| stc = p.storageClass; | ||
|
|
||
| // This mirrors hdrgen.visit(Parameter p) | ||
| if (p.type && p.type.mod & MODshared) | ||
| stc &= ~STCshared; | ||
|
|
||
| auto exps = new Expressions; | ||
|
|
||
| void push(string s) | ||
| { | ||
| exps.push(new StringExp(e.loc, cast(char*)s.ptr, cast(uint)s.length)); | ||
| } | ||
|
|
||
| if (stc & STCauto) | ||
| push("auto"); | ||
| if (stc & STCreturn) | ||
| push("return"); | ||
|
|
||
| if (stc & STCout) | ||
| push("out"); | ||
| else if (stc & STCref) | ||
| push("ref"); | ||
| else if (stc & STCin) | ||
| push("in"); | ||
| else if (stc & STClazy) | ||
| push("lazy"); | ||
| else if (stc & STCalias) | ||
| push("alias"); | ||
|
|
||
| if (stc & STCconst) | ||
| push("const"); | ||
| if (stc & STCimmutable) | ||
| push("immutable"); | ||
| if (stc & STCwild) | ||
| push("inout"); | ||
| if (stc & STCshared) | ||
| push("shared"); | ||
| if (stc & STCscope) | ||
| push("scope"); | ||
|
|
||
| auto tup = new TupleExp(e.loc, exps); | ||
| return tup.semantic(sc); | ||
| } | ||
| if (e.ident == Id.getLinkage) | ||
| { | ||
| // get symbol linkage as a string | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/test17425.d(24): Error: parameter index must be in range 0..4 not 4 | ||
| fail_compilation/test17425.d(27): Error: first argument to `__traits(getParameterStorageClasses, i, 4)` is not a function | ||
| fail_compilation/test17425.d(29): Error: expression expected as second argument of `__traits(getParameterStorageClasses, foo, int)` | ||
| fail_compilation/test17425.d(31): Error: expected 2 arguments for `getParameterStorageClasses` but had 3 | ||
| --- | ||
| */ | ||
|
|
||
| // https://issues.dlang.org/show_bug.cgi?id=17425 | ||
|
|
||
| ref int foo(return ref const int* p, scope int* a, out int b, lazy int c); | ||
|
|
||
| //pragma(msg, __traits(getParameterStorageClasses, foo, 0)); | ||
|
|
||
| static assert(__traits(getParameterStorageClasses, foo, 0)[0] == "return"); | ||
| static assert(__traits(getParameterStorageClasses, foo, 0)[1] == "ref"); | ||
|
|
||
| //pragma(msg, __traits(getParameterStorageClasses, foo, 1)); | ||
| static assert(__traits(getParameterStorageClasses, foo, 1)[0] == "scope"); | ||
| static assert(__traits(getParameterStorageClasses, foo, 2)[0] == "out"); | ||
| static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy"); | ||
|
|
||
| enum a1 = __traits(getParameterStorageClasses, foo, 4); | ||
|
|
||
| int i; | ||
| enum a2 = __traits(getParameterStorageClasses, i, 4); | ||
|
|
||
| enum a3 = __traits(getParameterStorageClasses, foo, int); | ||
|
|
||
| enum a4 = __traits(getParameterStorageClasses, foo, 0, 1); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changelog entry seems a bit terse. I'd use at least more descriptive variable names. Also, linking to the documentation instead of bugzilla might be more helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI the auto-tester allows to preview this since some time (though I am not sure why this isn't part of the diff, CC @CyberShadow)
In any case the link is e.g. http://dtest.dlang.io/artifact/website-72ba79b73f635fb08bdfe69d6826833c1c4c2ee0-a9052bf749bf29e4ae70eb23d51613de/web/changelog/2.075.0_pre.html#changelog17425 (the _pre file in the changelog folder).
FWIW there also seems to be a parenthesis problem in another changelog file..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't link to the documentation because that PR has not been pulled.