Merge "Don't allow user-defined uninitialized const variables to be exported."
diff --git a/slang_rs_context.cpp b/slang_rs_context.cpp
index 6b07804..bc674a0 100644
--- a/slang_rs_context.cpp
+++ b/slang_rs_context.cpp
@@ -77,8 +77,6 @@
bool RSContext::processExportVar(const clang::VarDecl *VD) {
slangAssert(!VD->getName().empty() && "Variable name should not be empty");
- // TODO(zonr): some check on variable
-
RSExportType *ET = RSExportType::CreateFromDecl(this, VD);
if (!ET)
return false;
@@ -231,8 +229,25 @@
switch (D->getKind()) {
case clang::Decl::Var: {
clang::VarDecl* VD = llvm::dyn_cast<clang::VarDecl>(D);
+ bool ShouldExportVariable = true;
if (VD->getFormalLinkage() == clang::ExternalLinkage) {
- if (!processExportVar(VD)) {
+ clang::QualType QT = VD->getTypeSourceInfo()->getType();
+ if (QT.isConstQualified() && !VD->hasInit()) {
+ if (Slang::IsLocInRSHeaderFile(VD->getLocation(),
+ *getSourceManager())) {
+ // We don't export variables internal to the runtime's
+ // implementation.
+ ShouldExportVariable = false;
+ } else {
+ clang::DiagnosticsEngine *DiagEngine = getDiagnostics();
+ DiagEngine->Report(VD->getLocation(), DiagEngine->getCustomDiagID(
+ clang::DiagnosticsEngine::Error,
+ "invalid declaration of uninitialized constant variable '%0'"))
+ << VD->getName();
+ valid = false;
+ }
+ }
+ if (valid && ShouldExportVariable && !processExportVar(VD)) {
valid = false;
}
}
diff --git a/tests/F_extern_const/extern_const.rs b/tests/F_extern_const/extern_const.rs
new file mode 100644
index 0000000..bf630de
--- /dev/null
+++ b/tests/F_extern_const/extern_const.rs
@@ -0,0 +1,4 @@
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+extern const int extern_const_int;
diff --git a/tests/F_extern_const/stderr.txt.expect b/tests/F_extern_const/stderr.txt.expect
new file mode 100644
index 0000000..567c9a5
--- /dev/null
+++ b/tests/F_extern_const/stderr.txt.expect
@@ -0,0 +1 @@
+extern_const.rs:4:18: error: invalid declaration of uninitialized constant variable 'extern_const_int'
diff --git a/tests/F_extern_const/stdout.txt.expect b/tests/F_extern_const/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/F_extern_const/stdout.txt.expect
diff --git a/tests/P_constant/constant.rs b/tests/P_constant/constant.rs
index 6f98ff1..4457e37 100644
--- a/tests/P_constant/constant.rs
+++ b/tests/P_constant/constant.rs
@@ -18,3 +18,5 @@
const bool boolTest = true;
+extern const int i = 5;
+
diff --git a/tests/P_constant/stderr.txt.expect b/tests/P_constant/stderr.txt.expect
index e69de29..3728bee 100644
--- a/tests/P_constant/stderr.txt.expect
+++ b/tests/P_constant/stderr.txt.expect
@@ -0,0 +1 @@
+constant.rs:21:18: warning: 'extern' variable has an initializer
diff --git a/tests/P_extern_const/extern_const.rs b/tests/P_extern_const/extern_const.rs
new file mode 100644
index 0000000..e80906a
--- /dev/null
+++ b/tests/P_extern_const/extern_const.rs
@@ -0,0 +1,7 @@
+// -I .
+#pragma version(1)
+#pragma rs java_package_name(foo)
+
+int __attribute__((kernel)) foo() {
+ return my_extern_const_in_header;
+}
diff --git a/tests/P_extern_const/rs_core.rsh b/tests/P_extern_const/rs_core.rsh
new file mode 100644
index 0000000..4332ed0
--- /dev/null
+++ b/tests/P_extern_const/rs_core.rsh
@@ -0,0 +1,8 @@
+// Fake rs_core.rsh header file
+//
+// We use -I . to pick up this header file implicitly, instead of the proper
+// rs_core.rsh header file.
+
+// Declare an uninitialized external constant, which should be ok for our
+// official header files.
+extern const int my_extern_const_in_header;
diff --git a/tests/P_extern_const/stderr.txt.expect b/tests/P_extern_const/stderr.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_extern_const/stderr.txt.expect
diff --git a/tests/P_extern_const/stdout.txt.expect b/tests/P_extern_const/stdout.txt.expect
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/P_extern_const/stdout.txt.expect