Add a command-line option to allow function names with the "rs" prefix (--allow-rs-prefix).  When not specified, user-defined functions with that prefix will be treated as an error.

Change-Id: Ieefc8bb55d61980241d5392ffb32770a303ce6a7
diff --git a/libslang.cpp b/libslang.cpp
index e774cae..7f8f545 100644
--- a/libslang.cpp
+++ b/libslang.cpp
@@ -8,6 +8,12 @@
     return (SlangCompiler*) slang;
 }
 
+extern "C" void slangAllowRSPrefix(SlangCompiler* compiler) {
+    Slang* slang = (Slang*) compiler;
+    if(slang != NULL)
+        slang->allowRSPrefix();
+}
+
 extern "C" int slangSetSourceFromMemory(SlangCompiler* compiler, const char* text, size_t textLength) {
     Slang* slang = (Slang*) compiler;
     if(slang != NULL)
diff --git a/libslang.h b/libslang.h
index b197167..3be3e46 100644
--- a/libslang.h
+++ b/libslang.h
@@ -22,6 +22,8 @@
 
 SlangCompiler* slangCreateCompiler(const char* targetTriple, const char* targetCPU, const char** targetFeatures);
 
+void slangAllowRSPrefix();
+
 int slangSetSourceFromMemory(SlangCompiler* compiler, const char* text, size_t textLength);
 int slangSetSourceFromFile(SlangCompiler* compiler, const char* fileName);
 
diff --git a/slang.cpp b/slang.cpp
index 4071ada..59fd029 100644
--- a/slang.cpp
+++ b/slang.cpp
@@ -92,7 +92,8 @@
 }
 
 Slang::Slang(const char* Triple, const char* CPU, const char** Features) :
-    mOutputType(SlangCompilerOutput_Default)
+    mOutputType(SlangCompilerOutput_Default),
+    mAllowRSPrefix(false)
 {
     GlobalInitialization();
 
@@ -243,4 +244,3 @@
 }
 
 }   /* namespace slang */
-
diff --git a/slang.hpp b/slang.hpp
index 0dbf00c..4f4ff44 100644
--- a/slang.hpp
+++ b/slang.hpp
@@ -131,7 +131,8 @@
                                    mPragmas,
                                    mOS.take(),
                                    mOutputType,
-                                   *mSourceMgr));
+                                   *mSourceMgr,
+                                   mAllowRSPrefix));
 
         return;
     }
@@ -144,7 +145,8 @@
                                      mPragmas,
                                      mOS.take(),
                                      mOutputType,
-                                     *mSourceMgr));
+                                     *mSourceMgr,
+                                     mAllowRSPrefix));
 
         return;
     }
@@ -158,6 +160,8 @@
     /* Output stream */
     llvm::OwningPtr<llvm::raw_ostream> mOS;
 
+    bool mAllowRSPrefix;
+
 public:
     static const std::string TargetDescription;
 
@@ -181,6 +185,10 @@
 
     bool setOutput(const char* outputFile);
 
+    inline void allowRSPrefix() {
+        mAllowRSPrefix = true;
+    }
+
     int compile();
 
     bool reflectToJava(const char* outputPackageName);
diff --git a/slang_backend.cpp b/slang_backend.cpp
index 6142775..5249483 100644
--- a/slang_backend.cpp
+++ b/slang_backend.cpp
@@ -128,7 +128,8 @@
                  const PragmaList& Pragmas,
                  llvm::raw_ostream* OS,
                  SlangCompilerOutputTy OutputType,
-                 SourceManager &SourceMgr) :
+                 SourceManager &SourceMgr,
+                 bool AllowRSPrefix) :
     ASTConsumer(),
     mLLVMContext(llvm::getGlobalContext()),
     mDiags(Diags),
@@ -143,7 +144,8 @@
     mPerFunctionPasses(NULL),
     mPerModulePasses(NULL),
     mCodeGenPasses(NULL),
-    mSourceMgr(SourceMgr)
+    mSourceMgr(SourceMgr),
+    mAllowRSPrefix(AllowRSPrefix)
 {
     FormattedOutStream.setStream(*mpOS, llvm::formatted_raw_ostream::PRESERVE_STREAM);
     mGen = CreateLLVMCodeGen(mDiags, "", mCodeGenOpts, mLLVMContext);
@@ -161,13 +163,15 @@
 
 void Backend::HandleTopLevelDecl(DeclGroupRef D) {
     /* Disallow user-defined functions with prefix "rs" */
-    DeclGroupRef::iterator it;
-    for (it = D.begin(); it != D.end(); it++) {
-        FunctionDecl *FD = dyn_cast<FunctionDecl>(*it);
-        if (!FD || !FD->isThisDeclarationADefinition()) continue;
-        if (FD->getName().startswith("rs")) {
-            mDiags.Report(FullSourceLoc(FD->getLocStart(), mSourceMgr),
-                          mDiags.getCustomDiagID(Diagnostic::Warning, "invalid function name prefix, \"rs\" is reserved: '%0'")) << FD->getNameAsString();
+    if (!mAllowRSPrefix) {
+        DeclGroupRef::iterator it;
+        for (it = D.begin(); it != D.end(); it++) {
+            FunctionDecl *FD = dyn_cast<FunctionDecl>(*it);
+            if (!FD || !FD->isThisDeclarationADefinition()) continue;
+            if (FD->getName().startswith("rs")) {
+                mDiags.Report(FullSourceLoc(FD->getLocStart(), mSourceMgr),
+                              mDiags.getCustomDiagID(Diagnostic::Error, "invalid function name prefix, \"rs\" is reserved: '%0'")) << FD->getNameAsString();
+            }
         }
     }
 
diff --git a/slang_backend.hpp b/slang_backend.hpp
index f57eed6..4c1c8af 100644
--- a/slang_backend.hpp
+++ b/slang_backend.hpp
@@ -49,6 +49,8 @@
 
     SourceManager& mSourceMgr;
 
+    bool mAllowRSPrefix;
+
     /* Output stream */
     llvm::raw_ostream* mpOS;
     SlangCompilerOutputTy mOutputType;
@@ -121,7 +123,8 @@
             const PragmaList& Pragmas,
             llvm::raw_ostream* OS,
             SlangCompilerOutputTy OutputType,
-            SourceManager& SourceMgr);
+            SourceManager& SourceMgr,
+            bool AllowRSPrefix);
 
     /*
      * Initialize - This is called to initialize the consumer, providing the
diff --git a/slang_driver.cpp b/slang_driver.cpp
index f502169..0eaf425 100644
--- a/slang_driver.cpp
+++ b/slang_driver.cpp
@@ -173,16 +173,19 @@
 static const char* InputFileName;
 static bool Verbose;
 static const char* FeatureEnabledList[MaxTargetFeature + 1];
+static int AllowRSPrefix = 0;
 
 /* Construct the command options table used in ParseOption::getopt_long */
 static void ConstructCommandOptions() {
     /* Basic slang command option */
     static struct option BasicSlangOpts[] = {
-        { "emit-llvm",      no_argument, (int*) &OutputFileType, SlangCompilerOutput_LL },
-        { "emit-bc",        no_argument, (int*) &OutputFileType, SlangCompilerOutput_Bitcode },
-        { "emit-asm",       no_argument, NULL, 'S' },
-        { "emit-obj",       no_argument, NULL, 'c' },
-        { "emit-nothing",   no_argument, (int*) &OutputFileType, SlangCompilerOutput_Nothing },
+        { "allow-rs-prefix", no_argument, &AllowRSPrefix, 1 },
+
+        { "emit-llvm",       no_argument, (int*) &OutputFileType, SlangCompilerOutput_LL },
+        { "emit-bc",         no_argument, (int*) &OutputFileType, SlangCompilerOutput_Bitcode },
+        { "emit-asm",        no_argument, NULL, 'S' },
+        { "emit-obj",        no_argument, NULL, 'c' },
+        { "emit-nothing",    no_argument, (int*) &OutputFileType, SlangCompilerOutput_Nothing },
 
         { "help",    no_argument, NULL, 'h' }, /* -h */
         { "verbose", no_argument, NULL, 'v' }, /* -v */
@@ -249,7 +252,8 @@
     cout << "Basic: " << endl;
 
     OUTPUT_OPTION("-h", "--help", "print this help");
-    OUTPUT_OPTION("-v", "--verbos", "be verbose");
+    OUTPUT_OPTION("-v", "--verbose", "be verbose");
+    OUTPUT_OPTION(NULL, "--allow-rs-prefix", "Allow user-defined function names with the \"rs\" prefix");
     OUTPUT_OPTION("-o", "--output=<FILE>", "write the output of compilation to FILE ('-' means stdout)");
     OUTPUT_OPTION("-j", "--output-java-reflection-package=<PACKAGE NAME>", "output reflection to Java for BCC exportables");
 
@@ -524,6 +528,9 @@
 
             slangSetOutputType(slang, OutputFileType);
 
+            if (AllowRSPrefix)
+                slangAllowRSPrefix();
+
             SLANG_CALL_AND_CHECK( slangSetOutputToFile(slang, OutputFileName) );
 
             SLANG_CALL_AND_CHECK( slangCompile(slang) <= 0 );
diff --git a/slang_rs_backend.cpp b/slang_rs_backend.cpp
index 4555416..a819d5f 100644
--- a/slang_rs_backend.cpp
+++ b/slang_rs_backend.cpp
@@ -31,7 +31,8 @@
                      const PragmaList& Pragmas,
                      llvm::raw_ostream* OS,
                      SlangCompilerOutputTy OutputType,
-                     SourceManager& SourceMgr) :
+                     SourceManager& SourceMgr,
+                     bool AllowRSPrefix) :
     mContext(Context),
     Backend(Diags,
             CodeGenOpts,
@@ -39,7 +40,8 @@
             Pragmas,
             OS,
             OutputType,
-            SourceMgr),
+            SourceMgr,
+            AllowRSPrefix),
     mExportVarMetadata(NULL)
 {
     return;
diff --git a/slang_rs_backend.hpp b/slang_rs_backend.hpp
index 5d76404..8f471e1 100644
--- a/slang_rs_backend.hpp
+++ b/slang_rs_backend.hpp
@@ -50,7 +50,8 @@
               const PragmaList& Pragmas,
               llvm::raw_ostream* OS,
               SlangCompilerOutputTy OutputType,
-              SourceManager& SourceMgr);
+              SourceManager& SourceMgr,
+              bool AllowRSPrefix);
 
     virtual void HandleTopLevelDecl(DeclGroupRef D);