-
Notifications
You must be signed in to change notification settings - Fork 273
Fully process always_inline (second attempt) #1898
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
Conversation
313a2be
to
a614345
Compare
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.
Some questions inline. Also, why do we have this at all? Surely always-inline is an optimisation that we could reasonably ignore?
// this is a GCC extension | ||
|
||
#ifdef __GNUC__ | ||
static inline __attribute__((always_inline)) _Bool |
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.
Could you minimise this test-case so it's clearer which parts are crucial to the test and which is unrelated stuff the kernel's RCU code happens to do? If you want to keep the real-world example you could include this as a block comment, then use a simplified version for the actual test?
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.
Actually everything is necessary here, but I'll add comments to explain why/what it is testing.
^SIGNAL=0$ | ||
-- | ||
^warning: ignoring | ||
^CONVERSION ERROR$ |
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.
Add a comment to the test specifying why we expect an error
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.
Done.
sym_entry->second.type.get_bool(ID_C_inlined) && | ||
sym_entry->second.is_macro && sym_entry->second.value.is_not_nil()) | ||
{ | ||
// calling a function marked as always_inline |
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.
Or, presumably, a macro? Or is the is_macro
flag only used for functions that are not in fact macros?
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.
Yes, is_macro
isn't ever used with (preprocessor) macros.
src/ansi-c/c_typecheck_expr.cpp
Outdated
if(p_it == parameters.end()) | ||
{ | ||
err_location(f_op); | ||
error() << "function call has additional arguments, " |
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.
More arguments than parameters, i.e. varargs?
typecheck_code(body); | ||
return_type.swap(cur_return_type); | ||
|
||
// replace final return by an ID_expression |
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.
Could there be other returns? If so what happens?
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.
It's unsupported - now it's being tested for and reported.
} | ||
|
||
codet body = to_code(func_sym.value); | ||
replace(body); |
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.
So this will replace formal parameters with actuals, but not actually cause locals to alias because they retain the qualified names (f::1::x
vs. g::1::x
) they had originally? That seems right for inlining but wrong for macros?
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.
As said above, we don't actually do preprocessor macros in this way, so it should be fine.
Gah, sorry, I understand now -- this code is trying to cause a compile error if it can't prove something is constant? |
Yes, I believe that's the way that some code in the Linux kernel uses it. |
@smowton Thanks a lot for all the comments, I will carefully review my code to come up with proper answers or fixes. |
0ee1b0c
to
99c12c6
Compare
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.
This looks good except that using "macro" to refer to things that are not macros, and never to refer to things that are macros, is maddening. Please change this if at all possible.
@@ -164,6 +166,9 @@ void ansi_c_declarationt::to_symbol( | |||
symbol.is_extern=false; | |||
else if(get_is_extern()) // traditional GCC | |||
symbol.is_file_local=true; | |||
|
|||
if(get_is_always_inline()) | |||
symbol.is_macro = true; |
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.
Can we please rename this then? It's really confusing that things annotated is_macro
and things that are macros are disjoint (!)
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 also note we have symbolt::is_function
which returns false if is_macro
is set!
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.
Upon further thought I'm inclined to say that is_macro
actually is the right terminology for all the current uses: all of them (typedefs, enum values, linker aliases, always-inline functions) are names with some value (which might be code) behind them and need to be expanded in place in order to evaluate the expression or statement they are involved in. We currently consume code after the C/C++ preprocessor has been run, so those kinds of "macros" are not currently seen - but actually, if they were, they would fit the very same definition and would likely be marked as such.
This is used int the precursor of a typechecked sizeof expression.
The Linux kernel uses tests on __builtin_constant_p that are required to evalute to true for compilationt to succeed. These can only evaluate to true when inlining is actually done (and expressions are simplified).
Macros are as local as types; we use macros for always-inlined functions, and contained symbols never end up in the symbol table. Thus macros must be removed before attempting to recurse into them for the purpose of symbol-table cleanup.
a10dd0c
to
688a0ab
Compare
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.
Passed Diffblue compatibility checks (cbmc commit: 688a0ab).
Partial revert of #1898 (always_inline support, second attempt)
8a7893c Merge pull request diffblue#2375 from diffblue/unit-dependencies 9258284 fix build depenencies of unit test binary f7cd161 Merge pull request diffblue#2371 from diffblue/fix-tests2 82753bc make test independent of index type f5f32da Merge pull request diffblue#2364 from smowton/smowton/fix/autodetect-default-cxx-dialect d437f60 Merge pull request diffblue#2368 from polgreen/doc_replace_func_bodies 6048517 Merge pull request diffblue#2353 from tautschnig/g++8-fixes2 e2e6d82 Merge pull request diffblue#2190 from tautschnig/more-stats 7210136 Make it clearer that <=> will always be stringified 560f82b Travis: test more g++ and clang versions d46a55c Add new goto-instrument option print-global-state-size 961b29a Silence GCC 8's warning about using realloc/memmove on non-POD ca1b03c Documentation wording for replace function bodies d8c5a98 Cleanup options handling of count-eloc, list-eloc, print-path-lengths 6cd6d31 Unit test framwork: use references when catching exceptions 6882da6 Merge pull request diffblue#2367 from diffblue/fix-tests bcc3bef make regression/cbmc/bounds_check1 independent of types used 4de4538 switch regression/cbmc/Typecast2 to preprocessed code 91a9c64 Amend two tests that explicitly target C++98 2b2b797 goto-gcc: select default language standard depending on emulated compiler 52a8afc Merge pull request diffblue#1898 from tautschnig/always-inline cbe691b Merge pull request diffblue#2363 from diffblue/Makefile-TAR 9d40a9e Merge pull request diffblue#2365 from diffblue/solaris_errno 9efd705 add model for ___errno for Solaris 11 eaa2e05 update Solaris instructions 2f142d5 allow customizing the tar command for solver download 8cc1848 Merge pull request diffblue#1860 from tautschnig/restore-irept-sharing fea5db0 Merge pull request diffblue#2361 from diffblue/fix-goto2 7c0d750 Merge pull request diffblue#2362 from smowton/smowton/fix/tolerate-cxx-namespace-attribute e440a25 introduce INCOMPLETE_GOTO and turn guarded goto into a stateless pass 1f1835b C++ frontend: tolerate namespace attributes cbce4bc Unit test of irept's public API abdb044 Unit test to check that irept implements sharing d58fd18 Silence the linter on assert in irep.h 3d64070 Partially revert "Use small intrusive pointer in irep" 688a0ab Macros are not needed outside translation units 9c93f59 Fully interpret __attribute__((always_inline)) d1f617b Apply symbol replacement in type_arg members git-subtree-dir: cbmc git-subtree-split: 8a7893c
This was previously proposed and merged in #1510, but had to be reverted in #1527. #1519 then provided an additional test, which is now included (together with the fix).