1/*
2 * Copyright 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "slang_rs_special_func.h"
18
19#include "clang/AST/ASTContext.h"
20#include "clang/AST/Attr.h"
21
22#include "slang_assert.h"
23#include "slang_version.h"
24
25namespace slang {
26
27bool RSSpecialFunc::isGraphicsRootRSFunc(unsigned int targetAPI,
28                                         const clang::FunctionDecl *FD) {
29  if (FD->hasAttr<clang::KernelAttr>()) {
30    return false;
31  }
32
33  if (!FD->getName().equals("root")) {
34    return false;
35  }
36
37  if (FD->getNumParams() == 0) {
38    // Graphics root function
39    return true;
40  }
41
42  // Check for legacy graphics root function (with single parameter).
43  if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
44    const clang::QualType &IntType = FD->getASTContext().IntTy;
45    if (FD->getReturnType().getCanonicalType() == IntType) {
46      return true;
47    }
48  }
49
50  return false;
51}
52
53bool
54RSSpecialFunc::validateSpecialFuncDecl(unsigned int targetAPI,
55                                       slang::RSContext *Context,
56                                       clang::FunctionDecl const *FD) {
57  slangAssert(Context && FD);
58  bool valid = true;
59  const clang::ASTContext &C = FD->getASTContext();
60  const clang::QualType &IntType = FD->getASTContext().IntTy;
61
62  if (isGraphicsRootRSFunc(targetAPI, FD)) {
63    if ((targetAPI < SLANG_ICS_TARGET_API) && (FD->getNumParams() == 1)) {
64      // Legacy graphics root function
65      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
66      clang::QualType QT = PVD->getType().getCanonicalType();
67      if (QT != IntType) {
68        Context->ReportError(PVD->getLocation(),
69                             "invalid parameter type for legacy "
70                             "graphics root() function: %0")
71            << PVD->getType();
72        valid = false;
73      }
74    }
75
76    // Graphics root function, so verify that it returns an int
77    if (FD->getReturnType().getCanonicalType() != IntType) {
78      Context->ReportError(FD->getLocation(),
79                           "root() is required to return "
80                           "an int for graphics usage");
81      valid = false;
82    }
83  } else if (isInitRSFunc(FD) || isDtorRSFunc(FD)) {
84    if (FD->getNumParams() != 0) {
85      Context->ReportError(FD->getLocation(),
86                           "%0(void) is required to have no "
87                           "parameters")
88          << FD->getName();
89      valid = false;
90    }
91
92    if (FD->getReturnType().getCanonicalType() != C.VoidTy) {
93      Context->ReportError(FD->getLocation(),
94                           "%0(void) is required to have a void "
95                           "return type")
96          << FD->getName();
97      valid = false;
98    }
99  } else {
100    slangAssert(false && "must be called on root, init or .rs.dtor function!");
101  }
102
103  return valid;
104}
105
106}  // namespace slang
107