Bug 401256 - extract local variable doesn't work on parameters to macros
Summary: extract local variable doesn't work on parameters to macros
Status: NEW
Alias: None
Product: CDT
Classification: Tools
Component: cdt-refactoring (show other bugs)
Version: 8.2   Edit
Hardware: PC Linux-GTK
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact: Jonah Graham CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-19 20:15 EST by Matt Hargett CLA
Modified: 2020-09-04 15:17 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Hargett CLA 2013-02-19 20:15:08 EST
Version: 8.2.0.201302052218

having trouble narrowing this down, but this is a reduction of an issue I was having in trying to use various refactorings on the cgreen open source project.

my reduction:
void myprint(const char *);
#define MACRO(result) if (result) myprint("[" #result "]")
int main(void) {
	MACRO(1); // can't extract 1
	return 0;
}

placing the caret at the 1 and pressing alt+shift+L gives the error that an expression must be selected. highlighting the 1 and trying again gives the same message.

steps:
in the real code, 
-check out svn://matt_hargett@svn.code.sf.net/p/cgreen/code/trunk/cgreen
-create a new project by importing existing code as makefile project
-after indexing is complete, open mocks_tests.c
-in can_stub_an_integer_return, try to extract a local variable for integer_out() from the line
assert_that(integer_out(), is_equal_to(3));

result:
an expression must be selected to activate this refactoring

expected result:
should add a new line "int integerOut = integer_out();" and modify the existing assert_that line to be "assert_that(integerOut, is_equal_to(3));"


PS: trying a simple "assert_true(false);" in an existing cgreen test and attempt to extract the "false" into a local variable also fails.
Comment 1 Sergey Prigogin CLA 2013-02-19 20:23:52 EST
(In reply to comment #0)
> 	MACRO(1); // can't extract 1

The parameter to the macro is not an expression because it gets converted to a string by the macro. Extracting a variable for an arbitrary sequence of tokens cannot be done reliably.
Comment 2 Matt Hargett CLA 2013-02-20 01:01:51 EST
okay, that explains my attempt at a reduced example. in the actual cgreen code, the types should be inferrable despite the stringification. any comments there?
Comment 3 Sergey Prigogin CLA 2013-02-20 01:56:51 EST
(In reply to comment #2)
> okay, that explains my attempt at a reduced example. in the actual cgreen
> code, the types should be inferrable despite the stringification. any
> comments there?

Stringification means that the macro parameter doesn't map to an AST expression, doesn't it?
Comment 4 Matt Hargett CLA 2013-02-20 17:05:22 EST
okay, I've simplified the macro to remove string-ification and it still won't extract:

#define my_assert_true(result) \
        (*get_test_reporter()->assert_true)(get_test_reporter(), "", 0, result, "[", NULL)

Ensure(no_errors_thrown_and_default_return_value_when_no_presets_for_loose_mock) {
	my_assert_true(0); // can't extract local var for 'false'
}

some of the other relevant declarations:
typedef struct TestReporter_ TestReporter;
struct TestReporter_ {
    void (*destroy)(TestReporter *reporter);
    void (*start_suite)(TestReporter *reporter, const char *name, const int count);
    void (*start_test)(TestReporter *reporter, const char *name);
    void (*show_pass)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
    void (*show_fail)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
    void (*show_incomplete)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
    void (*assert_true)(TestReporter *reporter, const char *file, int line, int result, const char * message, ...);
    void (*finish_test)(TestReporter *reporter, const char *file, int line);
    void (*finish_suite)(TestReporter *reporter, const char *file, int line);
    int passes;
    int failures;
    int exceptions;
    void *breadcrumb;
    int ipc;
    void *memo;
};

TestReporter *get_test_reporter();


the AST knows that get_test_reporter() returns a TestReporter*, and it also knows the parameter list (and types) for the assert_true function pointer on the TestReporter. It should be able to determine that the macro parameter is being substituted for fourth parameter, and the type is int, and therefore extract a local variable "int result = 0;"

Again, this small project's source code is open so this can be more easily tested in-context. See initial comments for the svn URL.

Thanks!