Clean up graphics/compute root() distinction.

BUG=6000538

Change-Id: I29096556dff2072a8757e0dfd3321006cd60bb27
diff --git a/slang_rs_context.cpp b/slang_rs_context.cpp
index b55750f..5d4f26d 100644
--- a/slang_rs_context.cpp
+++ b/slang_rs_context.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2010-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -116,20 +116,17 @@
     return false;
   }
 
-  if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
+  if (RSExportForEach::isSpecialRSFunc(mTargetAPI, FD)) {
+    // Do not reflect specialized functions like init, dtor, or graphics root.
+    return RSExportForEach::validateSpecialFuncDecl(mTargetAPI,
+                                                    getDiagnostics(), FD);
+  } else if (RSExportForEach::isRSForEachFunc(mTargetAPI, FD)) {
     RSExportForEach *EFE = RSExportForEach::Create(this, FD);
     if (EFE == NULL)
       return false;
     else
       mExportForEach.push_back(EFE);
     return true;
-  } else if (RSExportForEach::isSpecialRSFunc(FD)) {
-    // Do not reflect specialized RS functions like init or graphics root.
-    if (!RSExportForEach::validateSpecialFuncDecl(mTargetAPI,
-                                                  getDiagnostics(), FD)) {
-      return false;
-    }
-    return true;
   }
 
   RSExportFunc *EF = RSExportFunc::Create(this, FD);
diff --git a/slang_rs_export_foreach.cpp b/slang_rs_export_foreach.cpp
index 0dbf954..76eb0f1 100644
--- a/slang_rs_export_foreach.cpp
+++ b/slang_rs_export_foreach.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * Copyright 2011-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -293,6 +293,28 @@
   return FE;
 }
 
+bool RSExportForEach::isGraphicsRootRSFunc(int targetAPI,
+                                           const clang::FunctionDecl *FD) {
+  if (!isRootRSFunc(FD)) {
+    return false;
+  }
+
+  if (FD->getNumParams() == 0) {
+    // Graphics root function
+    return true;
+  }
+
+  // Check for legacy graphics root function (with single parameter).
+  if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
+    const clang::QualType &IntType = FD->getASTContext().IntTy;
+    if (FD->getResultType().getCanonicalType() == IntType) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 bool RSExportForEach::isRSForEachFunc(int targetAPI,
     const clang::FunctionDecl *FD) {
   // We currently support only compute root() being exported via forEach
@@ -300,22 +322,10 @@
     return false;
   }
 
-  if (FD->getNumParams() == 0) {
-    // Graphics compute function
+  if (isGraphicsRootRSFunc(targetAPI, FD)) {
     return false;
   }
 
-  // Handle legacy graphics root functions.
-  if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
-    const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
-    clang::QualType QT = PVD->getType().getCanonicalType();
-    const clang::QualType &IntType = FD->getASTContext().IntTy;
-    if ((FD->getResultType().getCanonicalType() == IntType) &&
-        (QT == IntType)) {
-      return false;
-    }
-  }
-
   return true;
 }
 
@@ -326,26 +336,34 @@
   slangAssert(DiagEngine && FD);
   bool valid = true;
   const clang::ASTContext &C = FD->getASTContext();
+  const clang::QualType &IntType = FD->getASTContext().IntTy;
 
-  if (isRootRSFunc(FD)) {
-    unsigned int numParams = FD->getNumParams();
-    if (numParams == 0) {
-      // Graphics root function, so verify that it returns an int
-      if (FD->getResultType().getCanonicalType() != C.IntTy) {
+  if (isGraphicsRootRSFunc(targetAPI, FD)) {
+    if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
+      // Legacy graphics root function
+      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
+      clang::QualType QT = PVD->getType().getCanonicalType();
+      if (QT != IntType) {
         DiagEngine->Report(
-          clang::FullSourceLoc(FD->getLocation(),
+          clang::FullSourceLoc(PVD->getLocation(),
                                DiagEngine->getSourceManager()),
           DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
-                                      "root(void) is required to return "
-                                      "an int for graphics usage"));
+                                      "invalid parameter type for legacy "
+                                      "graphics root() function: %0"))
+          << PVD->getType();
         valid = false;
       }
-    } else if ((targetAPI < SLANG_ICS_TARGET_API) && (numParams == 1)) {
-      // Legacy graphics root function
-      // This has already been validated in isRSForEachFunc().
-    } else {
-      slangAssert(false &&
-          "Should not call validateSpecialFuncDecl() on compute root()");
+    }
+
+    // Graphics root function, so verify that it returns an int
+    if (FD->getResultType().getCanonicalType() != IntType) {
+      DiagEngine->Report(
+        clang::FullSourceLoc(FD->getLocation(),
+                             DiagEngine->getSourceManager()),
+        DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error,
+                                    "root() is required to return "
+                                    "an int for graphics usage"));
+      valid = false;
     }
   } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) {
     if (FD->getNumParams() != 0) {
diff --git a/slang_rs_export_foreach.h b/slang_rs_export_foreach.h
index bb9c1a0..c511f27 100644
--- a/slang_rs_export_foreach.h
+++ b/slang_rs_export_foreach.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * Copyright 2011-2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -148,10 +148,15 @@
     return Name.equals(FuncDtor);
   }
 
+  static bool isGraphicsRootRSFunc(int targetAPI,
+                                   const clang::FunctionDecl *FD);
+
   static bool isRSForEachFunc(int targetAPI, const clang::FunctionDecl *FD);
 
-  inline static bool isSpecialRSFunc(const clang::FunctionDecl *FD) {
-    return isRootRSFunc(FD) || isInitRSFunc(FD) || isDtorRSFunc(FD);
+  inline static bool isSpecialRSFunc(int targetAPI,
+                                     const clang::FunctionDecl *FD) {
+    return isGraphicsRootRSFunc(targetAPI, FD) || isInitRSFunc(FD) ||
+           isDtorRSFunc(FD);
   }
 
   static bool validateSpecialFuncDecl(int targetAPI,
diff --git a/tests/F_multi_export_errors/stderr.txt.expect b/tests/F_multi_export_errors/stderr.txt.expect
index f982c30..a39a137 100644
--- a/tests/F_multi_export_errors/stderr.txt.expect
+++ b/tests/F_multi_export_errors/stderr.txt.expect
@@ -1,3 +1,3 @@
 multi_export_errors.rs:4:5: error: init(void) is required to have a void return type
-multi_export_errors.rs:8:6: error: root(void) is required to return an int for graphics usage
+multi_export_errors.rs:8:6: error: root() is required to return an int for graphics usage
 multi_export_errors.rs:11:5: error: invokable non-static functions are required to return void
diff --git a/tests/F_root_graphics/stderr.txt.expect b/tests/F_root_graphics/stderr.txt.expect
index cf56bad..6b1e04d 100644
--- a/tests/F_root_graphics/stderr.txt.expect
+++ b/tests/F_root_graphics/stderr.txt.expect
@@ -1 +1 @@
-root_graphics.rs:4:6: error: root(void) is required to return an int for graphics usage
+root_graphics.rs:4:6: error: root() is required to return an int for graphics usage
diff --git a/tests/F_root_graphics_13/stderr.txt.expect b/tests/F_root_graphics_13/stderr.txt.expect
index 5670930..74e9ee0 100644
--- a/tests/F_root_graphics_13/stderr.txt.expect
+++ b/tests/F_root_graphics_13/stderr.txt.expect
@@ -1,3 +1 @@
-root_graphics_13.rs:5:5: error: compute root() is required to return a void type
-root_graphics_13.rs:5:5: error: Compute root() must have at least one parameter for in or out
-root_graphics_13.rs:5:5: error: Compute root() targeting SDK levels 11-13 may not skip parameters
+root_graphics_13.rs:5:23: error: invalid parameter type for legacy graphics root() function: 'unsigned int'