Bug fix: support self-referential struct type.
diff --git a/slang_rs_export_type.cpp b/slang_rs_export_type.cpp
index 1028eb6..6542c5d 100644
--- a/slang_rs_export_type.cpp
+++ b/slang_rs_export_type.cpp
@@ -86,7 +86,6 @@
           return cname;                                       \
         break;
 #include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
         default: {
           assert(false && "Unknown data type of the builtin");
           break;
@@ -165,7 +164,6 @@
 #define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname)  \
         case builtin_type:
 #include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
           return T;
         default: {
           return NULL;
@@ -403,11 +401,12 @@
   return;
 }
 
-void RSExportType::keep() {
+bool RSExportType::keep() {
+  if (!RSExportable::keep())
+    return false;
   // Invalidate converted LLVM type.
   mLLVMType = NULL;
-  RSExportable::keep();
-  return;
+  return true;
 }
 
 bool RSExportType::equals(const RSExportable *E) const {
@@ -437,7 +436,6 @@
 #define ENUM_RS_OBJECT_TYPE(type, cname)                            \
     RSObjectTypeMap->GetOrCreateValue(cname, DataType ## type);
 #include "RSObjectTypeEnums.inc"
-#undef ENUM_RS_OBJECT_TYPE
   }
 
   RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
@@ -460,7 +458,6 @@
 #define ENUM_RS_DATA_TYPE(type, cname, bits)  \
   bits,
 #include "RSDataTypeEnums.inc"
-#undef ENUM_RS_DATA_TYPE
   0   // DataTypeMax
 };
 
@@ -485,7 +482,6 @@
           return DataType ## type;                            \
         }
 #include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
         // The size of type WChar depend on platform so we abandon the support
         // to them.
         default: {
@@ -637,9 +633,11 @@
   return llvm::PointerType::getUnqual(PointeeType);
 }
 
-void RSExportPointerType::keep() {
+bool RSExportPointerType::keep() {
+  if (!RSExportType::keep())
+    return false;
   const_cast<RSExportType*>(mPointeeType)->keep();
-  RSExportType::keep();
+  return true;
 }
 
 bool RSExportPointerType::equals(const RSExportable *E) const {
@@ -672,7 +670,6 @@
       break;                                                  \
     }
 #include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
     default: {
       return llvm::StringRef();
     }
@@ -819,10 +816,11 @@
   return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
 }
 
-void RSExportConstantArrayType::keep() {
+bool RSExportConstantArrayType::keep() {
+  if (!RSExportType::keep())
+    return false;
   const_cast<RSExportType*>(mElementType)->keep();
-  RSExportType::keep();
-  return;
+  return true;
 }
 
 bool RSExportConstantArrayType::equals(const RSExportable *E) const {
@@ -903,10 +901,14 @@
 }
 
 const llvm::Type *RSExportRecordType::convertToLLVMType() const {
+  // Create an opaque type since struct may reference itself recursively.
+  llvm::PATypeHolder ResultHolder =
+      llvm::OpaqueType::get(getRSContext()->getLLVMContext());
+  setAbstractLLVMType(ResultHolder.get());
+
   std::vector<const llvm::Type*> FieldTypes;
 
-  for (const_field_iterator FI = fields_begin(),
-           FE = fields_end();
+  for (const_field_iterator FI = fields_begin(), FE = fields_end();
        FI != FE;
        FI++) {
     const Field *F = *FI;
@@ -915,20 +917,27 @@
     FieldTypes.push_back(FET->getLLVMType());
   }
 
-  return llvm::StructType::get(getRSContext()->getLLVMContext(),
-                               FieldTypes,
-                               mIsPacked);
+  llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
+                                               FieldTypes,
+                                               mIsPacked);
+  if (ST != NULL)
+    static_cast<llvm::OpaqueType*>(ResultHolder.get())
+        ->refineAbstractTypeTo(ST);
+  else
+    return NULL;
+  return ResultHolder.get();
 }
 
-void RSExportRecordType::keep() {
+bool RSExportRecordType::keep() {
+  if (!RSExportType::keep())
+    return false;
   for (std::list<const Field*>::iterator I = mFields.begin(),
           E = mFields.end();
        I != E;
        I++) {
     const_cast<RSExportType*>((*I)->getType())->keep();
   }
-  RSExportType::keep();
-  return;
+  return true;
 }
 
 bool RSExportRecordType::equals(const RSExportable *E) const {
diff --git a/slang_rs_export_type.h b/slang_rs_export_type.h
index 60685cb..6dcaa44 100644
--- a/slang_rs_export_type.h
+++ b/slang_rs_export_type.h
@@ -110,6 +110,11 @@
   // (all of these information are target dependent) without dealing with these
   // by ourselves.
   virtual const llvm::Type *convertToLLVMType() const = 0;
+  // Record type may recursively referece its type definition. We need a
+  // temporary type setup before the type construction gets done.
+  inline void setAbstractLLVMType(const llvm::Type *LLVMType) const {
+    mLLVMType = LLVMType;
+  }
 
   virtual ~RSExportType() {}
  public:
@@ -138,7 +143,7 @@
 
   inline const std::string &getName() const { return mName; }
 
-  virtual void keep();
+  virtual bool keep();
   virtual bool equals(const RSExportable *E) const;
 };  // RSExportType
 
@@ -154,7 +159,6 @@
 #define ENUM_RS_DATA_TYPE(type, cname, bits)  \
     DataType ## type,
 #include "RSDataTypeEnums.inc"
-#undef ENUM_RS_DATA_TYPE
 
     DataTypeMax
   } DataType;
@@ -165,7 +169,6 @@
 #define ENUM_RS_DATA_KIND(kind) \
     , DataKind ## kind
 #include "RSDataKindEnums.inc"
-#undef ENUM_RS_DATA_KIND
   } DataKind;
 
  private:
@@ -261,7 +264,7 @@
  public:
   static const clang::Type *IntegerType;
 
-  virtual void keep();
+  virtual bool keep();
 
   inline const RSExportType *getPointeeType() const { return mPointeeType; }
 
@@ -367,7 +370,7 @@
   inline unsigned getSize() const { return mSize; }
   inline const RSExportType *getElementType() const { return mElementType; }
 
-  virtual void keep();
+  virtual bool keep();
   virtual bool equals(const RSExportable *E) const;
 };
 
@@ -447,7 +450,7 @@
   inline bool isArtificial() const { return mIsArtificial; }
   inline size_t getAllocSize() const { return mAllocSize; }
 
-  virtual void keep();
+  virtual bool keep();
   virtual bool equals(const RSExportable *E) const;
 
   ~RSExportRecordType() {
diff --git a/slang_rs_exportable.cpp b/slang_rs_exportable.cpp
index 53ab33d..6e60582 100644
--- a/slang_rs_exportable.cpp
+++ b/slang_rs_exportable.cpp
@@ -18,10 +18,12 @@
 
 using namespace slang;
 
-void RSExportable::keep() {
+bool RSExportable::keep() {
+  if (isKeep())
+    return false;
   // Invalidate associated Context.
   mContext = NULL;
-  return;
+  return true;
 }
 
 bool RSExportable::equals(const RSExportable *E) const {
diff --git a/slang_rs_exportable.h b/slang_rs_exportable.h
index c3d0215..f336745 100644
--- a/slang_rs_exportable.h
+++ b/slang_rs_exportable.h
@@ -48,7 +48,8 @@
   // When keep() is invoked, mKeep will set to true and the associated RSContext
   // won't free this RSExportable object in its destructor. The deallcation
   // responsibility is then transferred to the object who invoked this function.
-  virtual void keep();
+  // Return false if the exportable is kept or failed to keep.
+  virtual bool keep();
   inline bool isKeep() const { return (mContext == NULL); }
 
   virtual bool equals(const RSExportable *E) const;
diff --git a/slang_rs_spec_table.cpp b/slang_rs_spec_table.cpp
index 6ef4e64..f08b28d 100644
--- a/slang_rs_spec_table.cpp
+++ b/slang_rs_spec_table.cpp
@@ -188,6 +188,7 @@
            DataTypes[i]->getTypeName(),
            DataTypes[i]->getTypePragmaName(),
            DataTypes[i]->getSizeInBit());
+  printf("#undef ENUM_RS_DATA_TYPE");
   return 0;
 }
 
@@ -203,6 +204,7 @@
            ClangBuilitinsMap[i]->getBuiltinTypeKind(),
            ClangBuilitinsMap[i]->getDataType()->getTypeName(),
            ClangBuilitinsMap[i]->getDataType()->getTypePragmaName());
+  printf("#undef ENUM_SUPPORT_BUILTIN_TYPE");
   return 0;
 }
 
@@ -217,6 +219,7 @@
       printf("ENUM_RS_OBJECT_TYPE(%s, \"%s\")\n",
              DataTypes[i]->getTypeName(),
              DataTypes[i]->getTypePragmaName());
+  printf("#undef ENUM_RS_OBJECT_TYPE");
   return 0;
 }
 
@@ -228,6 +231,7 @@
                        unsigned NumDataKinds) {
   for (unsigned i = 0; i < NumDataKinds; i++)
     printf("ENUM_RS_DATA_KIND(%s)\n", DataKinds[i]->getKindName());
+  printf("#undef ENUM_RS_DATA_KIND");
   return 0;
 }
 
@@ -244,6 +248,7 @@
            DataElements[i]->getDataType()->getTypeName(),
            ((DataElements[i]->isNormal()) ? "true" : "false"),
            DataElements[i]->getVectorSize());
+  printf("#undef ENUM_RS_DATA_ELEMENT");
   return 0;
 }