]> granicus.if.org Git - clang/commitdiff
Fix predefine for __NSConstantString struct type
authorBen Langmuir <blangmuir@apple.com>
Thu, 4 Feb 2016 00:55:24 +0000 (00:55 +0000)
committerBen Langmuir <blangmuir@apple.com>
Thu, 4 Feb 2016 00:55:24 +0000 (00:55 +0000)
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
include/clang/Serialization/ASTBitCodes.h
lib/AST/ASTContext.cpp
lib/Sema/Sema.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/CodeGenObjC/2010-02-01-utf16-with-null.m
test/CodeGenObjC/arc-no-arc-exceptions.m
test/CodeGenObjC/tentative-cfconstantstring.m
test/Modules/Inputs/builtin.h
test/Modules/builtins.m

index 1d053411ebc24502555d9f667fb70eb1171cc316..438e676a97982e61a2c1024308b4bc0201589025 100644 (file)
@@ -253,8 +253,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
   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);
index 6ca9f54bc883fcd8d45f76365cfcf45e622e5911..32c33388d1e1d5ad63ad830c4ec31635922cae39 100644 (file)
@@ -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;
index fc5ff8668e9539cd43681ab3670fe2ce89f65e7c..06fb46e2f7f2e4de719fdd59552fa5500abf9402 100644 (file)
@@ -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<RecordType>();
-  assert(Rec && "Invalid CFConstantStringType");
-  CFConstantStringTypeDecl = Rec->getDecl();
+  const TypedefType *TD = T->getAs<TypedefType>();
+  assert(TD && "Invalid CFConstantStringType");
+  CFConstantStringTypeDecl = cast<TypedefDecl>(TD->getDecl());
+  auto TagType =
+      CFConstantStringTypeDecl->getUnderlyingType()->getAs<RecordType>();
+  assert(TagType && "Invalid CFConstantStringType");
+  CFConstantStringTagDecl = TagType->getDecl();
 }
 
 QualType ASTContext::getBlockDescriptorType() const {
index 3745cdd9a5920564dfeb48b18a53c90fbea7a775..584dca1e387a9c6ccea84232e45daa39f1c36443 100644 (file)
@@ -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 &&
index 1fbff107ea5bab240f08dd7483a19c7051c1922a..2fae0a65411547301f84eab4d47878f614a7265a 100644 (file)
@@ -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");
 }
index a590e188eca9e18bf77f311c9aecefaab9212123..0b28a7aa6736df7e9b12797b1431ac78cc41ff5b 100644 (file)
@@ -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
index 856ac9ac97bde9e7ff1d087745dc210c71f00005..7c103f2ba6d45e1f89167e5d409c8918ef5a3179 100644 (file)
@@ -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";
index 30424e7fb361f2512f54a2ddfe05b5672e41df7a..f147b64c4841caaa819615951ccb9a600a6f5dbb 100644 (file)
@@ -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
index 0c692c37c955e780d65b9203b6aeba287754cb58..9ff1a0a2fce2e4ae49a0bc0aed4987a2ac2141ba 100644 (file)
@@ -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
-
index d87794523420d8954eb21b08419e7c481c5addbf..4717ff2a52a28b82494b11d01e025dd78a01c03a 100644 (file)
@@ -1,10 +1,7 @@
 int i;
 int *p = &i;
 
-#ifdef __OBJC__
 void use_constant_string_builtins(void) {
   (void)__builtin___CFStringMakeConstantString("");
   (void)__builtin___NSStringMakeConstantString("");
 }
-#endif
-
index a835039cc60ba9f55bd12e882998b0bb7869774d..2480e6379cc85900e681f3c0b22fe339f422e829 100644 (file)
@@ -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);