r174794 - Ensure that type definitions present in just-loaded modules are

Douglas Gregor dgregor at apple.com
Fri Feb 8 17:35:04 PST 2013


Author: dgregor
Date: Fri Feb  8 19:35:03 2013
New Revision: 174794

URL: http://llvm.org/viewvc/llvm-project?rev=174794&view=rev
Log:
Ensure that type definitions present in just-loaded modules are
visible.

The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,

  class X;
  X *x;

and then import a module that includes a definition of X:

  import XDef;

We will then fail when attempting to access a member of X, e.g., 

  x->method()

because the AST reader did not know to look for a default of a class
named X within the new module.

This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.

In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,

  // module 1
  namespace N { struct X; }

  // module 2
  namespace N { struct X { /* ... */ }; }

One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.


Added:
    cfe/trunk/test/Modules/decldef.m
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/AST/ExternalASTSource.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/test/Modules/Inputs/def.h
    cfe/trunk/test/Modules/decldef.mm

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Feb  8 19:35:03 2013
@@ -2496,6 +2496,12 @@ protected:
   /// possible in C++11 or Microsoft extensions mode.
   bool IsFixed : 1;
 
+  /// \brief Indicates whether it is possible for declarations of this kind
+  /// to have an out-of-date definition.
+  ///
+  /// This option is only enabled when modules are enabled.
+  bool MayHaveOutOfDateDef : 1;
+
 private:
   SourceLocation RBraceLoc;
 

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Feb  8 19:35:03 2013
@@ -337,7 +337,10 @@ protected:
   static void *AllocateDeserializedDecl(const ASTContext &Context,
                                         unsigned ID,
                                         unsigned Size);
-  
+
+  /// \brief Update a potentially out-of-date declaration.
+  void updateOutOfDate(IdentifierInfo &II) const;
+
 public:
 
   /// \brief Source range that this declaration covers.

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Fri Feb  8 19:35:03 2013
@@ -668,11 +668,14 @@ class ObjCInterfaceDecl : public ObjCCon
 
   /// \brief Contains a pointer to the data associated with this class,
   /// which will be NULL if this class has not yet been defined.
-  DefinitionData *Data;
+  ///
+  /// The bit indicates when we don't need to check for out-of-date
+  /// declarations. It will be set unless modules are enabled.
+  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
 
   DefinitionData &data() const {
-    assert(Data != 0 && "Declaration has no definition!");
-    return *Data;
+    assert(Data.getPointer() && "Declaration has no definition!");
+    return *Data.getPointer();
   }
 
   /// \brief Allocate the definition data for this class.
@@ -680,7 +683,7 @@ class ObjCInterfaceDecl : public ObjCCon
   
   typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
   virtual ObjCInterfaceDecl *getNextRedeclaration() { 
-    return RedeclLink.getNext(); 
+    return RedeclLink.getNext();
   }
   virtual ObjCInterfaceDecl *getPreviousDeclImpl() {
     return getPreviousDecl();
@@ -853,24 +856,38 @@ public:
   /// \brief Determine whether this particular declaration of this class is
   /// actually also a definition.
   bool isThisDeclarationADefinition() const { 
-    return Data && Data->Definition == this;
+    return getDefinition() == this;
   }
                           
   /// \brief Determine whether this class has been defined.
-  bool hasDefinition() const { return Data; }
+  bool hasDefinition() const {
+    // If the name of this class is out-of-date, bring it up-to-date, which
+    // might bring in a definition.
+    // Note: a null value indicates that we don't have a definition and that
+    // modules are enabled.
+    if (!Data.getOpaqueValue()) {
+      if (IdentifierInfo *II = getIdentifier()) {
+        if (II->isOutOfDate()) {
+          updateOutOfDate(*II);
+        }
+      }
+    }
+
+    return Data.getPointer();
+  }
                         
   /// \brief Retrieve the definition of this class, or NULL if this class 
   /// has been forward-declared (with \@class) but not yet defined (with 
   /// \@interface).
   ObjCInterfaceDecl *getDefinition() {
-    return hasDefinition()? Data->Definition : 0;
+    return hasDefinition()? Data.getPointer()->Definition : 0;
   }
 
   /// \brief Retrieve the definition of this class, or NULL if this class 
   /// has been forward-declared (with \@class) but not yet defined (with 
   /// \@interface).
   const ObjCInterfaceDecl *getDefinition() const {
-    return hasDefinition()? Data->Definition : 0;
+    return hasDefinition()? Data.getPointer()->Definition : 0;
   }
 
   /// \brief Starts the definition of this Objective-C class, taking it from
@@ -1142,7 +1159,7 @@ public:
   /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation
   /// declaration without an \@interface declaration.
   bool isImplicitInterfaceDecl() const { 
-    return hasDefinition() ? Data->Definition->isImplicit() : isImplicit(); 
+    return hasDefinition() ? data().Definition->isImplicit() : isImplicit();
   }
 
   /// ClassImplementsProtocol - Checks that 'lProto' protocol
@@ -1319,12 +1336,17 @@ class ObjCProtocolDecl : public ObjCCont
     /// \brief Referenced protocols
     ObjCProtocolList ReferencedProtocols;    
   };
-  
-  DefinitionData *Data;
+
+  /// \brief Contains a pointer to the data associated with this class,
+  /// which will be NULL if this class has not yet been defined.
+  ///
+  /// The bit indicates when we don't need to check for out-of-date
+  /// declarations. It will be set unless modules are enabled.
+  llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
 
   DefinitionData &data() const {
-    assert(Data && "Objective-C protocol has no definition!");
-    return *Data;
+    assert(Data.getPointer() && "Objective-C protocol has no definition!");
+    return *Data.getPointer();
   }
   
   ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
@@ -1343,7 +1365,7 @@ class ObjCProtocolDecl : public ObjCCont
   virtual ObjCProtocolDecl *getMostRecentDeclImpl() {
     return getMostRecentDecl();
   }
-                           
+
 public:
   static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
                                   IdentifierInfo *Id,
@@ -1394,7 +1416,7 @@ public:
   /// implements.
   void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
                        const SourceLocation *Locs, ASTContext &C) {
-    assert(Data && "Protocol is not defined");
+    assert(hasDefinition() && "Protocol is not defined");
     data().ReferencedProtocols.set(List, Num, Locs, C);
   }
 
@@ -1411,16 +1433,30 @@ public:
   }
 
   /// \brief Determine whether this protocol has a definition.
-  bool hasDefinition() const { return Data != 0; }
+  bool hasDefinition() const {
+    // If the name of this protocol is out-of-date, bring it up-to-date, which
+    // might bring in a definition.
+    // Note: a null value indicates that we don't have a definition and that
+    // modules are enabled.
+    if (!Data.getOpaqueValue()) {
+      if (IdentifierInfo *II = getIdentifier()) {
+        if (II->isOutOfDate()) {
+          updateOutOfDate(*II);
+        }
+      }
+    }
+
+    return Data.getPointer();
+  }
 
   /// \brief Retrieve the definition of this protocol, if any.
   ObjCProtocolDecl *getDefinition() {
-    return Data? Data->Definition : 0;
+    return hasDefinition()? Data.getPointer()->Definition : 0;
   }
 
   /// \brief Retrieve the definition of this protocol, if any.
   const ObjCProtocolDecl *getDefinition() const {
-    return Data? Data->Definition : 0;
+    return hasDefinition()? Data.getPointer()->Definition : 0;
   }
 
   /// \brief Determine whether this particular declaration is also the 

Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Fri Feb  8 19:35:03 2013
@@ -118,6 +118,9 @@ public:
   /// The default implementation of this method is a no-op.
   virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
 
+  /// \brief Update an out-of-date identifier.
+  virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { }
+
   /// \brief Find all declarations with the given name in the given context,
   /// and add them to the context by calling SetExternalVisibleDeclsForName
   /// or SetNoExternalVisibleDeclsForName.

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Fri Feb  8 19:35:03 2013
@@ -2612,6 +2612,16 @@ void TagDecl::completeDefinition() {
 TagDecl *TagDecl::getDefinition() const {
   if (isCompleteDefinition())
     return const_cast<TagDecl *>(this);
+
+  // If it's possible for us to have an out-of-date definition, check now.
+  if (MayHaveOutOfDateDef) {
+    if (IdentifierInfo *II = getIdentifier()) {
+      if (II->isOutOfDate()) {
+        updateOutOfDate(*II);
+      }
+    }
+  }
+
   if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this))
     return CXXRD->getDefinition();
 
@@ -2668,14 +2678,17 @@ EnumDecl *EnumDecl::Create(ASTContext &C
                            bool IsScopedUsingClassTag, bool IsFixed) {
   EnumDecl *Enum = new (C) EnumDecl(DC, StartLoc, IdLoc, Id, PrevDecl,
                                     IsScoped, IsScopedUsingClassTag, IsFixed);
+  Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
   C.getTypeDeclType(Enum, PrevDecl);
   return Enum;
 }
 
 EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumDecl));
-  return new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0,
-                            false, false, false);
+  EnumDecl *Enum = new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(),
+                                      0, 0, false, false, false);
+  Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+  return Enum;
 }
 
 void EnumDecl::completeDefinition(QualType NewType,
@@ -2743,14 +2756,18 @@ RecordDecl *RecordDecl::Create(const AST
                                IdentifierInfo *Id, RecordDecl* PrevDecl) {
   RecordDecl* R = new (C) RecordDecl(Record, TK, DC, StartLoc, IdLoc, Id,
                                      PrevDecl);
+  R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+
   C.getTypeDeclType(R, PrevDecl);
   return R;
 }
 
 RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl));
-  return new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(),
-                              SourceLocation(), 0, 0);
+  RecordDecl *R = new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(),
+                                       SourceLocation(), 0, 0);
+  R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
+  return R;
 }
 
 bool RecordDecl::isInjectedClassName() const {

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Feb  8 19:35:03 2013
@@ -40,6 +40,10 @@ using namespace clang;
 #define ABSTRACT_DECL(DECL)
 #include "clang/AST/DeclNodes.inc"
 
+void Decl::updateOutOfDate(IdentifierInfo &II) const {
+  getASTContext().getExternalSource()->updateOutOfDateIdentifier(II);
+}
+
 void *Decl::AllocateDeserializedDecl(const ASTContext &Context, 
                                      unsigned ID,
                                      unsigned Size) {

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Feb  8 19:35:03 2013
@@ -87,6 +87,7 @@ CXXRecordDecl *CXXRecordDecl::Create(con
                                      bool DelayTypeCreation) {
   CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, StartLoc, IdLoc,
                                            Id, PrevDecl);
+  R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
 
   // FIXME: DelayTypeCreation seems like such a hack
   if (!DelayTypeCreation)
@@ -101,6 +102,7 @@ CXXRecordDecl *CXXRecordDecl::CreateLamb
                                            0, 0);
   R->IsBeingDefined = true;
   R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent);
+  R->MayHaveOutOfDateDef = false;
   C.getTypeDeclType(R, /*PrevDecl=*/0);
   return R;
 }
@@ -108,8 +110,11 @@ CXXRecordDecl *CXXRecordDecl::CreateLamb
 CXXRecordDecl *
 CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl));
-  return new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(),
-                                 SourceLocation(), 0, 0);
+  CXXRecordDecl *R = new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0,
+                                             SourceLocation(), SourceLocation(),
+                                             0, 0);
+  R->MayHaveOutOfDateDef = false;
+  return R;
 }
 
 void

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Fri Feb  8 19:35:03 2013
@@ -301,8 +301,8 @@ void ObjCInterfaceDecl::mergeClassExtens
 
 void ObjCInterfaceDecl::allocateDefinitionData() {
   assert(!hasDefinition() && "ObjC class already has a definition");
-  Data = new (getASTContext()) DefinitionData();
-  Data->Definition = this;
+  Data.setPointer(new (getASTContext()) DefinitionData());
+  Data.getPointer()->Definition = this;
 
   // Make the type point at the definition, now that we have one.
   if (TypeForDecl)
@@ -1011,6 +1011,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Cr
                                              bool isInternal){
   ObjCInterfaceDecl *Result = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, 
                                                         PrevDecl, isInternal);
+  Result->Data.setInt(!C.getLangOpts().Modules);
   C.getObjCInterfaceType(Result, PrevDecl);
   return Result;
 }
@@ -1018,8 +1019,11 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Cr
 ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(ASTContext &C, 
                                                          unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCInterfaceDecl));
-  return new (Mem) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(),
-                                     0, false);
+  ObjCInterfaceDecl *Result = new (Mem) ObjCInterfaceDecl(0, SourceLocation(),
+                                                          0, SourceLocation(),
+                                                          0, false);
+  Result->Data.setInt(!C.getLangOpts().Modules);
+  return Result;
 }
 
 ObjCInterfaceDecl::
@@ -1334,15 +1338,17 @@ ObjCProtocolDecl *ObjCProtocolDecl::Crea
                                            ObjCProtocolDecl *PrevDecl) {
   ObjCProtocolDecl *Result 
     = new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc, PrevDecl);
-  
+  Result->Data.setInt(!C.getLangOpts().Modules);
   return Result;
 }
 
 ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, 
                                                        unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCProtocolDecl));
-  return new (Mem) ObjCProtocolDecl(0, 0, SourceLocation(), SourceLocation(),
-                                    0);
+  ObjCProtocolDecl *Result = new (Mem) ObjCProtocolDecl(0, 0, SourceLocation(),
+                                                        SourceLocation(), 0);
+  Result->Data.setInt(!C.getLangOpts().Modules);
+  return Result;
 }
 
 ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
@@ -1380,9 +1386,9 @@ ObjCMethodDecl *ObjCProtocolDecl::lookup
 }
 
 void ObjCProtocolDecl::allocateDefinitionData() {
-  assert(!Data && "Protocol already has a definition!");
-  Data = new (getASTContext()) DefinitionData;
-  Data->Definition = this;
+  assert(!Data.getPointer() && "Protocol already has a definition!");
+  Data.setPointer(new (getASTContext()) DefinitionData);
+  Data.getPointer()->Definition = this;
 }
 
 void ObjCProtocolDecl::startDefinition() {

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Fri Feb  8 19:35:03 2013
@@ -728,6 +728,8 @@ ClassTemplateSpecializationDecl::Create(
                                                    SpecializedTemplate,
                                                    Args, NumArgs,
                                                    PrevDecl);
+  Result->MayHaveOutOfDateDef = false;
+
   Context.getTypeDeclType(Result, PrevDecl);
   return Result;
 }
@@ -737,7 +739,10 @@ ClassTemplateSpecializationDecl::CreateD
                                                     unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, 
                                        sizeof(ClassTemplateSpecializationDecl));
-  return new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
+  ClassTemplateSpecializationDecl *Result =
+    new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
+  Result->MayHaveOutOfDateDef = false;
+  return Result;
 }
 
 void
@@ -857,6 +862,7 @@ Create(ASTContext &Context, TagKind TK,D
                                                           PrevDecl,
                                                           SequenceNumber);
   Result->setSpecializationKind(TSK_ExplicitSpecialization);
+  Result->MayHaveOutOfDateDef = false;
 
   Context.getInjectedClassNameType(Result, CanonInjectedType);
   return Result;
@@ -867,7 +873,10 @@ ClassTemplatePartialSpecializationDecl::
                                                            unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, 
                 sizeof(ClassTemplatePartialSpecializationDecl));
-  return new (Mem) ClassTemplatePartialSpecializationDecl();
+  ClassTemplatePartialSpecializationDecl *Result
+    = new (Mem) ClassTemplatePartialSpecializationDecl();
+  Result->MayHaveOutOfDateDef = false;
+  return Result;
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/test/Modules/Inputs/def.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/def.h?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/def.h (original)
+++ cfe/trunk/test/Modules/Inputs/def.h Fri Feb  8 19:35:03 2013
@@ -8,4 +8,13 @@
 }
 @end
 
+ at interface Def
+- defMethod;
+ at end
 
+#ifdef __cplusplus
+class Def2 {
+public:
+  void func();
+};
+#endif

Added: cfe/trunk/test/Modules/decldef.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/decldef.m?rev=174794&view=auto
==============================================================================
--- cfe/trunk/test/Modules/decldef.m (added)
+++ cfe/trunk/test/Modules/decldef.m Fri Feb  8 19:35:03 2013
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify
+
+
+// In other file: expected-note {{previous definition is here}}
+
+ at class Def;
+Def *def;
+
+ at import decldef;
+A *a1; // expected-error{{unknown type name 'A'}}
+B *b1; // expected-error{{must use 'struct' tag to refer to type 'B'}}
+ at import decldef.Decl;
+
+A *a2;
+struct B *b;
+
+void testA(A *a) {
+  a->ivar = 17; // expected-error{{definition of 'A' must be imported from module 'decldef.Def' before it is required}}
+}
+
+void testB() {
+  B b; // Note: redundant error silenced
+}
+
+void testDef() {
+  [def defMethod];
+}

Modified: cfe/trunk/test/Modules/decldef.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/decldef.mm?rev=174794&r1=174793&r2=174794&view=diff
==============================================================================
--- cfe/trunk/test/Modules/decldef.mm (original)
+++ cfe/trunk/test/Modules/decldef.mm Fri Feb  8 19:35:03 2013
@@ -1,9 +1,18 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -I %S/Inputs -fmodules-cache-path=%t %s -verify
+// RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify
 
 
 // In other file: expected-note {{previous definition is here}}
 
+ at class Def;
+Def *def;
+class Def2;
+Def2 *def2;
+
+ at interface Unrelated
+- defMethod;
+ at end
+
 @import decldef;
 A *a1; // expected-error{{unknown type name 'A'}}
 B *b1; // expected-error{{unknown type name 'B'}}
@@ -19,3 +28,11 @@ void testA(A *a) {
 void testB() {
   B b; // Note: redundant error silenced
 }
+
+void testDef() {
+  [def defMethod];
+}
+
+void testDef2() {
+  def2->func();
+}





More information about the cfe-commits mailing list