From: Chris Lattner Date: Sat, 21 Jun 2008 21:44:18 +0000 (+0000) Subject: "this patch adds code generation hooks for Objective-C constant strings. It also... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=13fd7e5111032f54b538dd66d035b0ccc1f82467;p=clang "this patch adds code generation hooks for Objective-C constant strings. It also modifies Sema so that Objective-C constant strings are treated as untyped objects if the interface for the constant string class can not be found. This is consistent with Apple GCC. I thought it was consistent with GNU GCC, since this was causing failures when trying to compile GNUstep with (GNU) GCC, but it appears that this is not the case when attempting to produce a simple test case to demonstrate it. Possibly there is a way of making the error go away, but I haven't found out what it is yet." Patch by David Chisnall! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52599 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index cae1f4bb24..fe11a5fb0a 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -59,6 +59,10 @@ public: llvm::Constant *VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } + llvm::Constant *VisitObjCStringLiteral(const ObjCStringLiteral *E) { + return CGM.getObjCRuntime()->GenerateConstantString( + E->getString()->getStrData(), E->getString()->getByteLength()); + } llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { return Visit(E->getInitializer()); diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index e545fc12ee..f2cfdcab82 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -302,9 +302,10 @@ llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty, //constant strings. llvm::Constant *CGObjCGNU::GenerateConstantString(const char *String, const size_t length) { + std::string Str(String, String +length); std::vector Ivars; Ivars.push_back(NULLPtr); - Ivars.push_back(MakeConstantString(String)); + Ivars.push_back(MakeConstantString(Str)); Ivars.push_back(llvm::ConstantInt::get(IntTy, length)); llvm::Constant *ObjCStr = MakeGlobal( llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 920457e00c..1aed69ec2c 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -54,13 +54,17 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); Decl *IFace = LookupDecl(NSIdent, Decl::IDNS_Ordinary, TUScope); ObjCInterfaceDecl *strIFace = dyn_cast_or_null(IFace); - if (!strIFace) - return Diag(S->getLocStart(), diag::err_undef_interface, - NSIdent->getName()); - Context.setObjCConstantStringInterface(strIFace); + if (strIFace) + Context.setObjCConstantStringInterface(strIFace); } QualType t = Context.getObjCConstantStringInterface(); - t = Context.getPointerType(t); + // If there is no NSConstantString interface defined then treat constant + // strings as untyped objects and let the runtime figure it out later. + if (t == QualType()) { + t = Context.getObjCIdType(); + } else { + t = Context.getPointerType(t); + } return new ObjCStringLiteral(S, t, AtLoc); } @@ -298,9 +302,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage( else { ObjCInterfaceType *OCIReceiver =dyn_cast(receiverType); if (OCIReceiver == 0) { - Diag(lbrac, diag::error_bad_receiver_type, - RExpr->getType().getAsString()); - return true; + Diag(lbrac, diag::error_bad_receiver_type, + RExpr->getType().getAsString()); + return true; } ClassDecl = OCIReceiver->getDecl(); // FIXME: consider using InstanceMethodPool, since it will be faster diff --git a/test/Parser/objc-foreach-error-1.m b/test/Parser/objc-foreach-error-1.m index 693f12e2ff..76251abf33 100644 --- a/test/Parser/objc-foreach-error-1.m +++ b/test/Parser/objc-foreach-error-1.m @@ -17,8 +17,7 @@ int LOOP(); @implementation MyList (BasicTest) // expected-error {{cannot find interface declaration for 'MyList'}} - (void)compilerTestAgainst { MyList * el; // expected-error {{use of undeclared identifier 'MyList'}} - for (el in @"foo") // expected-error {{use of undeclared identifier 'el'}} \ - // expected-error {{cannot find interface declaration for 'NSConstantString'}} + for (el in @"foo") // expected-error {{use of undeclared identifier 'el'}} { LOOP(); } } @end diff --git a/test/Sema/missing-string-interface.m b/test/Sema/missing-string-interface.m deleted file mode 100644 index f96fb4c2e4..0000000000 --- a/test/Sema/missing-string-interface.m +++ /dev/null @@ -1,7 +0,0 @@ -// RUN: clang %s -verify -fsyntax-only - -@class NSString; - -// GCC considers this an error, so clang will... -NSString *s = @"123"; // expected-error: {{cannot find interface declaration for 'NSConstantString'}} - diff --git a/test/Sema/objc-property-8.m b/test/Sema/objc-property-8.m index a081f39ec4..8ca0afc1ed 100644 --- a/test/Sema/objc-property-8.m +++ b/test/Sema/objc-property-8.m @@ -68,7 +68,7 @@ extern NSString *PBXWindowDidChangeFirstResponderNotification; @synthesize query = _query; - (void) _clearQuery { - [self.query removeObserver: self forKeyPath: @"matches"]; // expected-error{{cannot find interface declaration for 'NSConstantString'}} + [self.query removeObserver: self forKeyPath: @"matches"]; } @end