From 9b1a01589da8938dcbe093bfe75d5d4c31fbcff2 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Thu, 4 Feb 2016 00:55:24 +0000 Subject: [PATCH] Fix predefine for __NSConstantString struct type Per review feedback the name was wrong and it can be used outside Objective-C. Unfortunately, making the internal struct visible broke some ASTMatchers tests that assumed that the first record decl would be from user code, rather than a builtin type. I'm worried that this will also affect users' code. So this patch adds a typedef to wrap the internal struct and only makes the typedef visible to namelookup. This is sufficient to allow the ASTReader to merge the decls we need without making the struct itself visible. rdar://problem/24425801 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@259734 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 10 ++-- include/clang/Serialization/ASTBitCodes.h | 7 ++- lib/AST/ASTContext.cpp | 52 ++++++++++++------- lib/Sema/Sema.cpp | 9 ++-- lib/Serialization/ASTReader.cpp | 3 ++ lib/Serialization/ASTWriter.cpp | 2 + test/CodeGenObjC/2010-02-01-utf16-with-null.m | 4 +- test/CodeGenObjC/arc-no-arc-exceptions.m | 2 +- test/CodeGenObjC/tentative-cfconstantstring.m | 5 +- test/Modules/Inputs/builtin.h | 3 -- test/Modules/builtins.m | 6 ++- 11 files changed, 64 insertions(+), 39 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 1d053411eb..438e676a97 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -253,8 +253,9 @@ class ASTContext : public RefCountedBase { mutable IdentifierInfo *MakeIntegerSeqName = nullptr; QualType ObjCConstantStringType; - mutable RecordDecl *CFConstantStringTypeDecl; - + mutable RecordDecl *CFConstantStringTagDecl; + mutable TypedefDecl *CFConstantStringTypeDecl; + mutable QualType ObjCSuperType; QualType ObjCNSStringType; @@ -1381,11 +1382,12 @@ public: /// if it hasn't yet been built. QualType getRawCFConstantStringType() const { if (CFConstantStringTypeDecl) - return getTagDeclType(CFConstantStringTypeDecl); + return getTypedefType(CFConstantStringTypeDecl); return QualType(); } void setCFConstantStringType(QualType T); - TagDecl *getCFConstantStringDecl() const; + TypedefDecl *getCFConstantStringDecl() const; + RecordDecl *getCFConstantStringTagDecl() const; // This setter/getter represents the ObjC type for an NSConstantString. void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl); diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 6ca9f54bc8..32c33388d1 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -988,15 +988,18 @@ namespace clang { /// \brief The internal '__make_integer_seq' template. PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13, - /// \brief The internal '__NSConstantString' type. + /// \brief The internal '__NSConstantString' typedef. PREDEF_DECL_CF_CONSTANT_STRING_ID = 14, + + /// \brief The internal '__NSConstantString' tag type. + PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 15, }; /// \brief The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. - const unsigned int NUM_PREDEF_DECL_IDS = 15; + const unsigned int NUM_PREDEF_DECL_IDS = 16; /// \brief Record code for a list of local redeclarations of a declaration. const unsigned int LOCAL_REDECLARATIONS = 50; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index fc5ff8668e..06fb46e2f7 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -738,12 +738,13 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, BuiltinVaListDecl(nullptr), BuiltinMSVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), - CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr), - FILEDecl(nullptr), jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), - ucontext_tDecl(nullptr), BlockDescriptorType(nullptr), - BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr), - FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr), - MakeIntegerSeqDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), + CFConstantStringTagDecl(nullptr), CFConstantStringTypeDecl(nullptr), + ObjCInstanceTypeDecl(nullptr), FILEDecl(nullptr), jmp_bufDecl(nullptr), + sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr), + BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr), + cudaConfigureCallDecl(nullptr), FirstLocalImport(), LastLocalImport(), + ExternCContext(nullptr), MakeIntegerSeqDecl(nullptr), SourceMgr(SM), + LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), @@ -4868,12 +4869,12 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { return 1; } -TagDecl *ASTContext::getCFConstantStringDecl() const { +TypedefDecl *ASTContext::getCFConstantStringDecl() const { if (!CFConstantStringTypeDecl) { - // This type is designed to be compatible with NSConstantString, but cannot - // use the same name, since NSConstantString is an interface. - CFConstantStringTypeDecl = buildImplicitRecord("__NSConstantString"); - CFConstantStringTypeDecl->startDefinition(); + assert(!CFConstantStringTagDecl && + "tag and typedef should be initialized together"); + CFConstantStringTagDecl = buildImplicitRecord("__NSConstantString_tag"); + CFConstantStringTagDecl->startDefinition(); QualType FieldTypes[4]; @@ -4888,7 +4889,7 @@ TagDecl *ASTContext::getCFConstantStringDecl() const { // Create fields for (unsigned i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl, + FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTagDecl, SourceLocation(), SourceLocation(), nullptr, FieldTypes[i], /*TInfo=*/nullptr, @@ -4896,18 +4897,29 @@ TagDecl *ASTContext::getCFConstantStringDecl() const { /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); - CFConstantStringTypeDecl->addDecl(Field); + CFConstantStringTagDecl->addDecl(Field); } - CFConstantStringTypeDecl->completeDefinition(); + CFConstantStringTagDecl->completeDefinition(); + // This type is designed to be compatible with NSConstantString, but cannot + // use the same name, since NSConstantString is an interface. + auto tagType = getTagDeclType(CFConstantStringTagDecl); + CFConstantStringTypeDecl = + buildImplicitTypedef(tagType, "__NSConstantString"); } return CFConstantStringTypeDecl; } +RecordDecl *ASTContext::getCFConstantStringTagDecl() const { + if (!CFConstantStringTagDecl) + getCFConstantStringDecl(); // Build the tag and the typedef. + return CFConstantStringTagDecl; +} + // getCFConstantStringType - Return the type used for constant CFStrings. QualType ASTContext::getCFConstantStringType() const { - return getTagDeclType(getCFConstantStringDecl()); + return getTypedefType(getCFConstantStringDecl()); } QualType ASTContext::getObjCSuperType() const { @@ -4920,9 +4932,13 @@ QualType ASTContext::getObjCSuperType() const { } void ASTContext::setCFConstantStringType(QualType T) { - const RecordType *Rec = T->getAs(); - assert(Rec && "Invalid CFConstantStringType"); - CFConstantStringTypeDecl = Rec->getDecl(); + const TypedefType *TD = T->getAs(); + assert(TD && "Invalid CFConstantStringType"); + CFConstantStringTypeDecl = cast(TD->getDecl()); + auto TagType = + CFConstantStringTypeDecl->getUnderlyingType()->getAs(); + assert(TagType && "Invalid CFConstantStringType"); + CFConstantStringTagDecl = TagType->getDecl(); } QualType ASTContext::getBlockDescriptorType() const { diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 3745cdd9a5..584dca1e38 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -189,12 +189,13 @@ void Sema::Initialize() { DeclarationName Protocol = &Context.Idents.get("Protocol"); if (IdResolver.begin(Protocol) == IdResolver.end()) PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope); - - DeclarationName ConstantString = &Context.Idents.get("NSConstantString"); - if (IdResolver.begin(ConstantString) == IdResolver.end()) - PushOnScopeChains(Context.getCFConstantStringDecl(), TUScope); } + // Create the internal type for the *StringMakeConstantString builtins. + DeclarationName ConstantString = &Context.Idents.get("__NSConstantString"); + if (IdResolver.begin(ConstantString) == IdResolver.end()) + PushOnScopeChains(Context.getCFConstantStringDecl(), TUScope); + // Initialize Microsoft "predefined C++ types". if (getLangOpts().MSVCCompat) { if (getLangOpts().CPlusPlus && diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 1fbff107ea..2fae0a6541 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -6447,6 +6447,9 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) { case PREDEF_DECL_CF_CONSTANT_STRING_ID: return Context.getCFConstantStringDecl(); + + case PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID: + return Context.getCFConstantStringTagDecl(); } llvm_unreachable("PredefinedDeclIDs unknown enum value"); } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index a590e188ec..0b28a7aa67 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4154,6 +4154,8 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, PREDEF_DECL_MAKE_INTEGER_SEQ_ID); RegisterPredefDecl(Context.CFConstantStringTypeDecl, PREDEF_DECL_CF_CONSTANT_STRING_ID); + RegisterPredefDecl(Context.CFConstantStringTagDecl, + PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID); // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for diff --git a/test/CodeGenObjC/2010-02-01-utf16-with-null.m b/test/CodeGenObjC/2010-02-01-utf16-with-null.m index 856ac9ac97..7c103f2ba6 100644 --- a/test/CodeGenObjC/2010-02-01-utf16-with-null.m +++ b/test/CodeGenObjC/2010-02-01-utf16-with-null.m @@ -2,6 +2,6 @@ // rdar://7589850 // CHECK: @.str = private unnamed_addr constant [9 x i16] [i16 103, i16 111, i16 111, i16 100, i16 0, i16 98, i16 121, i16 101, i16 0], section "__TEXT,__ustring", align 2 -// CHECK: @_unnamed_cfstring_ = private constant %struct.__NSConstantString { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([9 x i16]* @.str to i8*), i32 8 }, section "__DATA,__cfstring" -// CHECK: @P = global i8* bitcast (%struct.__NSConstantString* @_unnamed_cfstring_ to i8*), align 4 +// CHECK: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([9 x i16]* @.str to i8*), i32 8 }, section "__DATA,__cfstring" +// CHECK: @P = global i8* bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to i8*), align 4 void *P = @"good\0bye"; diff --git a/test/CodeGenObjC/arc-no-arc-exceptions.m b/test/CodeGenObjC/arc-no-arc-exceptions.m index 30424e7fb3..f147b64c48 100644 --- a/test/CodeGenObjC/arc-no-arc-exceptions.m +++ b/test/CodeGenObjC/arc-no-arc-exceptions.m @@ -34,7 +34,7 @@ void test1(id x) { void NSLog(id, ...); // CHECK-LABEL: define void @test2( -// CHECK: invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.__NSConstantString* @_unnamed_cfstring_ to i8*), i32* %{{.*}}) +// CHECK: invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to i8*), i32* %{{.*}}) // CHECK: to label %{{.*}} unwind label %{{.*}}, !clang.arc.no_objc_arc_exceptions ! // NO-METADATA-LABEL: define void @test2( // NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions diff --git a/test/CodeGenObjC/tentative-cfconstantstring.m b/test/CodeGenObjC/tentative-cfconstantstring.m index 0c692c37c9..9ff1a0a2fc 100644 --- a/test/CodeGenObjC/tentative-cfconstantstring.m +++ b/test/CodeGenObjC/tentative-cfconstantstring.m @@ -32,12 +32,11 @@ static inline void _inlineFunction() { @end // CHECK: @__CFConstantStringClassReference = common global [24 x i32] zeroinitializer, align 16 -// CHECK: @_unnamed_cfstring_{{.*}} = private constant %struct.__NSConstantString { i32* getelementptr inbounds ([24 x i32], [24 x i32]* @__CFConstantStringClassReference, i32 0, i32 0) +// CHECK: @_unnamed_cfstring_{{.*}} = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([24 x i32], [24 x i32]* @__CFConstantStringClassReference, i32 0, i32 0) // CHECK-LABEL: define internal void @_inlineFunction() // CHECK: [[ZERO:%.*]] = load %struct._class_t*, %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_ // CHECK-NEXT: [[ONE:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_ // CHECK-NEXT: [[TWO:%.*]] = bitcast %struct._class_t* [[ZERO]] to i8* -// CHECK-NEXT: call void (i8*, i8*, [[T:%.*]]*, ...) bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, [[T:%.*]]*, ...)*)(i8* [[TWO]], i8* [[ONE]], [[T:%.*]]* bitcast (%struct.__NSConstantString* @_unnamed_cfstring_{{.*}} to [[T:%.*]]*)) +// CHECK-NEXT: call void (i8*, i8*, [[T:%.*]]*, ...) bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, [[T:%.*]]*, ...)*)(i8* [[TWO]], i8* [[ONE]], [[T:%.*]]* bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_{{.*}} to [[T:%.*]]*)) // CHECK-NEXT: ret void - diff --git a/test/Modules/Inputs/builtin.h b/test/Modules/Inputs/builtin.h index d877945234..4717ff2a52 100644 --- a/test/Modules/Inputs/builtin.h +++ b/test/Modules/Inputs/builtin.h @@ -1,10 +1,7 @@ int i; int *p = &i; -#ifdef __OBJC__ void use_constant_string_builtins(void) { (void)__builtin___CFStringMakeConstantString(""); (void)__builtin___NSStringMakeConstantString(""); } -#endif - diff --git a/test/Modules/builtins.m b/test/Modules/builtins.m index a835039cc6..2480e6379c 100644 --- a/test/Modules/builtins.m +++ b/test/Modules/builtins.m @@ -1,5 +1,7 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs %s -verify +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs -x c %s -verify +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs -x objective-c++ %s -verify // RUN: rm -rf %t.pch.cache // RUN: %clang_cc1 -fmodules-cache-path=%t.pch.cache -fmodules -fimplicit-module-maps -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %S/Inputs/use-builtin.h @@ -12,13 +14,13 @@ void use_constant_string_builtins1(void) { (void)__builtin___NSStringMakeConstantString(""); } -@import builtin; +#include "builtin.h" int foo() { return __builtin_object_size(p, 0); } -@import builtin.sub; +#include "builtin_sub.h" int bar() { return __builtin_object_size(p, 0); -- 2.40.0