简体   繁体   中英

Objective-C class as C pointer type

clang builtin function "__builtin_NSStringMakeConstantString" returns const NSConstantString* ,

that is not an Objective-C retainable object.

I want to replace this function with my own, but there seems to be no way to declare NSConstantString* as non-Objective-C pointer in Objective-C++ (you can do it in Objective-C by using struct NSConstnatString* ). I am sure, that this function returns NSConstantString , because the following two lines output PK16NSConstantString :

printf("%s\n", typeid(__builtin___NSStringMakeConstantString("foo")).name());
printf("%s\n", typeid(const NSConstantString*).name());

Whenever I try to execute the following code I get error "Cannot initialize a variable of type 'const NSConstantString *' with an rvalue of type 'const NSConstantString *'":

const NSConstantString* a = __builtin___NSStringMakeConstantString("foo");

Everything works OK if I add bridge cast, so this means that NSConstantString* is returned as "raw" Objective-C pointer, but I have to create a function that returns exactly the same result as "__builtin _NSStringMakeConstantString", so I have no option to use __bridge.

Whenever I try to return const NSConstantString* from a function, it is always returned as an Objective-C retainable pointer and there seems to be no way to declare it as C pointer except this:

typedef typeof __builtin___NSStringMakeConstantString("") rawNSConstnatStringPtr;

So the question is: Is there a way to declare a nonretainable pointer to NSConstantString* (without using typeof)?

You think _builtin__NSStringMakeConstant returns NSConstantString , because the compiler is tricking you.

I suggest you check out the clang source code: http://llvm.org/docs/GettingStarted.html#git-mirror

Then search the source code: git grep __builtin___NSStringMakeConstantString . You find that it's defined in include/clang/Basic/Builtins.def like this:

BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")

The second argument is the function signature, and the comment at the top of the file explains what it means. The FC* part is the return type, and means “constant CFString const pointer”. That makes sense since CFString and NSString are toll-free bridged.

But it doesn't make sense because the error message specifically mentions NSConstantString . So git grep -w NSConstantString to see where that's coming from. You eventually find method ASTContext::getCFConstantStringType in lib/ast/ASTContext.cpp . This method creates a struct type declaration with the identifier NSConstantString , but it never adds the declaration to any scope (it doesn't call PushOnScopeChains or AddDecl ). So the NSConstantString identifier can appear in diagnostics, but you cannot access the type by name in your source code. The NSConstantString type declared in NSString.h is, as far as the compiler is concerned, unrelated to this synthesized type.

Anyway, the important question is why you want to override __builtin___NSStringMakeConstantString , which you did not say. If it's because you want to use your own constant string class, you're going about it the wrong way.

I don't think you can override that function, because it is built in to the compiler. You would need to modify the compiler source code if you want to change its meaning.

Also, I don't think the compiler actually uses that function to create Objective-C string literals. Running git grep __builtin___NSStringMakeConstantString doesn't turn up any places where the compiler generates a call to it. The compiler handles @"string" syntax in lib/Parse/ParseObjc.cpp and lib/Sema/SemaExprObjC.cpp (look for methods named ParseObjCStringLiteral in both files). The compiler looks up the NSConstantString type by name (which means it should get the one from the NSString.h header file) and creates an instance of ObjCStringLiteral with that type.

You should be able to make it look up a different class for the constant string type (instead of NSConstantString ) using the -fconstant-string-class command-line flag, but I don't know how well that works. This question implies that it might not work. Even if it does work, I think you're constrained to using the same memory layout as NSConstantString , in which case, why bother using a different class?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM