LLDB How to use a file-defined macro in OC - ios

Ive tried multiple variations of this, but none of them seem to work. Any ideas?
in ViewController.m
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 300, 300)];
view1.backgroundColor = [UIColor redColor];
[self.view addSubview:view1];
Another file UIView+Frame.h
I defined a color macro
#define RGBACOLOR(r,g,b,a) [UIColor colorWithRGB:r Green:g Blue:b Alpha:a]
Actual operation
When the program executes [self.view addSubview: view1];I am going to use LLDB to use the defined macros to modify the color, but it prompts an error and I do n’t know how to modify it.
The wrong result is as follows
(lldb) e view1.backgroundColor = (UIColor *)RGBACOLOR(0,0,0,1)
error: use of undeclared identifier 'RGBACOLOR'
(lldb)

Macros are not traditionally well supported by debug info. The DWARF standard (which is the most common one on macOS & other Unixen) has a way to store the information, but it is so verbose very few toolchains support it. So there's no natural way for the debugger to know about defines.
If you have a small number of fairly independent macros you want to use in debug expressions, you can put them in a .h file, and set that file as lldb's "expression prefix". This will get included into the source of every expression you run subsequently. Do this by:
(lldb) settings set target.expr-prefix ~/my-common-defines.h
You can't get too ambitious here (e.g. #include <unistd.h> won't work). The problem is that most system header files are conditioned by a set of other #defines. lldb doesn't know what their values are, so at some point preprocessing the expr-prefix will fail.
Alternatively, clang also has a concept called "modules" which is an attempt to make the collection of headers from some package more shareable for repeated compilation. It actually captures some of the info that would cause the expr-prefix parsing to fail. So if the macro you want to access is in a set of headers that are built into a Clang module, then you can import the module into lldb's expression context, and that will make the defines from the modules available as well. So for instance:
(lldb) expr -l objc -- #import Foundation
will make all the Foundation macro definitions available.
Similarly, if your headers are modular (this page goes into depth on what this means:
https://clang.llvm.org/docs/Modules.html
) then you can import the module you've created, and its defines will be available to the expression parser.

Related

Cannot resolve enum values by name in Xcode debugger

With an enum typedef'd in a global header file used throughout my project, I am unable to refer to the individual enum values by name while using lldb in Xcode.
For example, if I am stopped at a breakpoint anywhere the enum type is available, and I try to evaluate something at the lldb prompt in Xcode (e.g. (lldb) p (int)EnumConstant), lldb complains:
error: use of undeclared identifier 'EnumConstant'
Furthermore, if I try to set a conditional breakpoint using an enum constant in the condition (e.g. right-click breakpoint in Xcode > Edit Breakpoint... > Condition: EnumConstant == someLocalVar), then Xcode complains every time it tries to evaluate that condition at that breakpoint:
Stopped due to an error evaluating condition of breakpoint 1.1: "EnumConstant == someLocalVar"
Couldn't parse conditional expression:
error: use of undeclared identifier 'EnumConstant'
Xcode's code completion popover even resolves a suggestion for the enum constant when I begin typing the name in the "Edit Breakpoint..." window, so Xcode itself doesn't have a problem resolving it.
Is there an option I can set in lldb or Xcode so that lldb maintains the enum identifiers after compilation? I'm assuming the enum constants get translated to their ordinal value during compilation, causing the executable to discard the identifiers, but thats just my naive speculation.
When I use the equivalent code in a simple GNU C program in Linux or Cygwin (minus the class definitions obviously), but using gcc/gdb instead of Xcode/lldb, I don't have these problems. It is able to resolve the enum values no problem.
I've created a tiny Xcode iPhone project to demonstrate what I mean. Using any of the enum_t constants below within the ViewController.m context (the for-loop is a good place to demo) will produce the same results.
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
typedef enum
{
eZero, eOne, eTwo, eCOUNT
}
enum_t;
extern NSString const * const ENUM_STR[];
#end
ViewController.m:
#import "ViewController.h"
#implementation ViewController
NSString const * const ENUM_STR[eCOUNT] = { #"eZero", #"eOne", #"eTwo" };
- (void)viewDidLoad
{
[super viewDidLoad];
for (enum_t value = eZero; value < eCOUNT; ++value)
{
NSLog(#"%-8# = %d", ENUM_STR[value], value);
}
}
#end
This is a bug (fairly longstanding) in how the name->Debug Information lookup-accelerator tables for enums are built. While enum types are listed, enum values are not. That was surely done to save output debug info size - debug information gets quite big pretty quickly, and so there's a constant tension between the cost of adding more info and the utility of that more info. So far this one hasn't risen to the level of inclusion.
Anyway, doing a search through "all debug information for anything with a name that matches 'eZero'" is prohibitively slow even for decent sized projects, and gets really bad for large ones. So lldb always uses these name->Debug Info tables for its first level access.
Because the accelerator tables do contain the enum type by name (and more important for you typedefs by name as well), the workaround is to do:
(lldb) expr enum_t::eZero
(int) $0 = 0
Of course, if you have truly anonymous enums, then you are pretty much out of luck till this info gets added to the accelerator tables.
BTW, the Xcode symbol completion in the Debugger Console window is done using the Xcode SourceKit indexer, not lldb. So the completions offered from Xcode are not a reflection of lldb's knowledge of the program.
BBTW, gdb doesn't use compiler-made accelerator tables (these were an Apple extension up till the new DWARF 5 standard) but manually builds an index by scanning the debug info. That allows them to index whatever seems best to the debugger. OTOH, it makes debugger startup quite a bit slower for big projects.

Getting "Expected a type" error in XCode

I'm getting this error:
/Class/GData/OAuth/GDataOAuthViewControllerTouch.m:116:22: Expected a type
That line is:
authentication:(GDataOAuthAuthentication *)auth
Inside of this block of code:
- (id)initWithScope:(NSString *)scope
language:(NSString *)language
requestTokenURL:(NSURL *)requestURL
authorizeTokenURL:(NSURL *)authorizeURL
accessTokenURL:(NSURL *)accessURL
authentication:(GDataOAuthAuthentication *)auth
appServiceName:(NSString *)keychainAppServiceName
delegate:(id)delegate
finishedSelector:(SEL)finishedSelector {
NSString *nibName = [[self class] authNibName];
I'm a newb XCode developer. So far I've created and compiled a calculator app based from an online class but that's it.
Is this a library that is not being included?
Background: The previous developer abandoned the project and the owner sent the project code to me. I'm trying to replace the existing graphics with new graphics and recompile it with support for iOS 6, which I thought I should be able to do without any coding, but have run into this error and many others when I opened the project. I have the latest XCode.
The :22 (and the position of the caret within the editor) tell you exactly where on the line the error is. In this case it's telling you that where it sees GDataOAuthAuthentication it was expecting a type. So, implicitly, it doesn't recognise that GDataOAuthAuthentication is a type.
Objective-C still sits upon compilation units ala C — each .m file is compiled in isolation then the lot are linked together. You use #import (or #include if you want; #import just guarantees the same file won't be included twice) to give each individual file visible sight of any external definitions it needs.
So, that's a long-winded way of reaching the same conclusion as Rick did five minutes ago: you've probably omitted a necessary #import.
A few things to look for:
Did you #import the file where the GDataOAuthAuthentication type is defined? (e.g. #import "GDataOAuthAuthentication.h")
Is there a variable named GDataOAuthAuthentication which is causing the compiler to think GDataOAuthAuthentication is a variable not a type?

Fix "Lexical or Preprocessor Issue - Extension used" warning in Xcode?

I've inherited a new project, which has several retain cycle warnings caused by implicitly retaining self within various blocks.
In attempting to fix these, I've written
__weak typeof(self) weakSelf = self;
to create a weak reference for use within the block.
However, Xcode v. 5.1.1 is giving the cryptic warning
Lexical or Preprocessor Issue
Extension used
I'm at a loss here-- what does this mean and how can I get rid of it?
You get this warning for the use of typeof if "Pedantic Warnings" are enabled in the build settings.
From the "Quick Help" for this setting:
Description Issue all the warnings demanded by strict ISO C and ISO
C++; reject all programs that use forbidden extensions, and some other
programs that do not follow ISO C and ISO C++. For ISO C, follows the
version of the ISO C standard specified by any -std option used.
[GCC_WARN_PEDANTIC, -pedantic]
I am not an expert in (ISO) C standards, but according to
https://gcc.gnu.org/onlinedocs/gcc/Typeof.html:
If you are writing a header file that must work when included in ISO C
programs, write __typeof__ instead of typeof. See Alternate Keywords.
and http://clang.llvm.org/docs/UsersManual.html:
The parser recognizes “asm” and “typeof” as keywords in gnu* modes;
the variants “__asm__” and “__typeof__” are recognized in all modes.
you can use __typeof__ instead
if you don't want to disable the warning:
__weak __typeof__(self) weakSelf = self;

iOS Name of this way of building and returning an object in Objective-C

I'm trying to find out what this style of coding is called, is it an inline block? inline scope? what? What will the compiler create when it comes across one of these...
- (UIView *)createMyView {
return
({
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 0)];
/* set some stuff up on the view;
 */
view;
});
}
I'm asking because we're getting a lot of cxx_destruct calls in a crash log with lines numbers that are way bigger than the actual size of the file. I'm wondering if this way of coding adds some weird stuff to the way its built.
That is a "Statement Expression", which is a GCC feature (understood by Clang as well),
see http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html:
A compound statement enclosed in parentheses may appear as an
expression in GNU C. This allows you to use loops, switches, and local
variables within an expression.
The value of the expression is the value of the last subexpression in the compound statement.

'Undeclared Identifier' error with defined constants

My defined constants are giving me 'undeclared identifier' issues. I have them in a Constants.h file that I am including in my .pch file. I thought it might be something with my .pch file, however, if I delete it from there and try #import it in one of the classes where I need one of the constants, then I still get an 'undeclared identifier' error.
If I take each #define line and put them at the top of the .m class file directly, they work. So my syntax is correct.
So it's something with the .h file itself, but I have no idea what.
//
// Constants.h
// Sliding Drawer
#define kOffscreenX 320 // X coord when Sliding Drawer is offscreen
#define kVisibleX 40 // X coord when Sliding Drawer is visible
// WordlistButton
#define kNumScores 3
// Fonts
#define kMessageFontSize 14
#define kScoreFontSize 10
It's impossible to see the error only from this piece of code. Preprocessor tends to create very messy things, especially when there are circular imports involved.
You can try to delete the current compiled version of the header, note it's not in the derived data folder, it's in XCode's cache (see Project -> Build Setttings -> Precompiled Headers Cache Path).
However, if you have tried to import Constants.h directly and it didn't work, the problem may be somewhere else.
Are you sure there is only 1 file called Constants.h? Note you should use a prefix for your files (e.g. SAConstants.h if Smooth Almonds is your name) to avoid collision with Apple's headers or headers of the libraries you are using.
If you import the header directly, go to the .m file and tap on Product -> Generate Output -> Preprocessed File and find Constants.h import in it. Is it your header?
By the way, there is a nice article about avoiding this kind of things in precompiled headers http://qualitycoding.org/precompiled-headers/
I found this thread due to an other error upper case parameter in my define statement. I solved it for my issue with lower casing:
#define MSB(BTvalue) ((uint8_t) (BTvalue >> 8)) //threw this error
changing BTvalue to just value with lowercase parameter made me happy
#define MSB(value) ((uint8_t) (value >> 8))

Resources