Implement one-definition-rule (ODR) feature.
When compiling multiple RS files, we say two RS files A and B break ODR
iff:
1. They have at least one common struct named [S] and [S] will be reflected
to ScriptField_[S].java, and
2. [S] defined in A is not *exactly the same* (number of fields, field
type and field name) as the one defined in B.
This CL detects such error.
diff --git a/slang_rs_export_type.cpp b/slang_rs_export_type.cpp
index ca4e188..416cdfa 100644
--- a/slang_rs_export_type.cpp
+++ b/slang_rs_export_type.cpp
@@ -29,6 +29,10 @@
#include "slang_rs_context.h"
#include "slang_rs_export_element.h"
+#define CHECK_PARENT_EQUALITY(ParentClass, E) \
+ if (!ParentClass::equals(E)) \
+ return false;
+
using namespace slang;
/****************************** RSExportType ******************************/
@@ -413,7 +417,6 @@
ExportClass Class,
const llvm::StringRef &Name)
: RSExportable(Context, RSExportable::EX_TYPE),
- mContext(Context),
mClass(Class),
// Make a copy on Name since memory stored @Name is either allocated in
// ASTContext or allocated in GetTypeName which will be destroyed later.
@@ -428,6 +431,18 @@
return;
}
+void RSExportType::keep() {
+ // Invalidate converted LLVM type.
+ mLLVMType = NULL;
+ RSExportable::keep();
+ return;
+}
+
+bool RSExportType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportable, E);
+ return (static_cast<const RSExportType*>(E)->getClass() == getClass());
+}
+
/************************** RSExportPrimitiveType **************************/
llvm::ManagedStatic<RSExportPrimitiveType::RSObjectTypeMapTy>
RSExportPrimitiveType::RSObjectTypeMap;
@@ -649,6 +664,11 @@
return NULL;
}
+bool RSExportPrimitiveType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return (static_cast<const RSExportPrimitiveType*>(E)->getType() == getType());
+}
+
/**************************** RSExportPointerType ****************************/
const clang::Type *RSExportPointerType::IntegerType = NULL;
@@ -681,6 +701,17 @@
return llvm::PointerType::getUnqual(PointeeType);
}
+void RSExportPointerType::keep() {
+ const_cast<RSExportType*>(mPointeeType)->keep();
+ RSExportType::keep();
+}
+
+bool RSExportPointerType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return (static_cast<const RSExportPointerType*>(E)
+ ->getPointeeType()->equals(getPointeeType()));
+}
+
/***************************** RSExportVectorType *****************************/
const char* RSExportVectorType::VectorTypeNameStore[][3] = {
/* 0 */ { "char2", "char3", "char4" },
@@ -778,6 +809,12 @@
return llvm::VectorType::get(ElementType, getNumElement());
}
+bool RSExportVectorType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportPrimitiveType, E);
+ return (static_cast<const RSExportVectorType*>(E)->getNumElement()
+ == getNumElement());
+}
+
/***************************** RSExportMatrixType *****************************/
RSExportMatrixType *RSExportMatrixType::Create(RSContext *Context,
const clang::RecordType *RT,
@@ -849,6 +886,11 @@
return llvm::StructType::get(C, X, NULL);
}
+bool RSExportMatrixType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return (static_cast<const RSExportMatrixType*>(E)->getDim() == getDim());
+}
+
/************************* RSExportConstantArrayType *************************/
RSExportConstantArrayType
*RSExportConstantArrayType::Create(RSContext *Context,
@@ -878,6 +920,18 @@
return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
}
+void RSExportConstantArrayType::keep() {
+ const_cast<RSExportType*>(mElementType)->keep();
+ RSExportType::keep();
+ return;
+}
+
+bool RSExportConstantArrayType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+ return ((static_cast<const RSExportConstantArrayType*>(E)
+ ->getSize() == getSize()) && (mElementType->equals(E)));
+}
+
/**************************** RSExportRecordType ****************************/
RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
const clang::RecordType *RT,
@@ -966,3 +1020,34 @@
FieldTypes,
mIsPacked);
}
+
+void RSExportRecordType::keep() {
+ for (std::list<const Field*>::iterator I = mFields.begin(),
+ E = mFields.end();
+ I != E;
+ I++) {
+ const_cast<RSExportType*>((*I)->getType())->keep();
+ }
+ RSExportType::keep();
+ return;
+}
+
+bool RSExportRecordType::equals(const RSExportable *E) const {
+ CHECK_PARENT_EQUALITY(RSExportType, E);
+
+ const RSExportRecordType *ERT = static_cast<const RSExportRecordType*>(E);
+
+ if (ERT->getFields().size() != getFields().size())
+ return false;
+
+ const_field_iterator AI = fields_begin(), BI = ERT->fields_begin();
+
+ for (unsigned i = 0, e = getFields().size(); i != e; i++) {
+ if (!(*AI)->getType()->equals((*BI)->getType()))
+ return false;
+ AI++;
+ BI++;
+ }
+
+ return true;
+}