111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines/*
211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * Copyright 2012, The Android Open Source Project
311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines *
411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * you may not use this file except in compliance with the License.
611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * You may obtain a copy of the License at
711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines *
811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines *
1011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * Unless required by applicable law or agreed to in writing, software
1111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
1211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * See the License for the specific language governing permissions and
1411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines * limitations under the License.
1511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines */
1611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
17f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala#include "clang/AST/Attr.h"
18f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala
1911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_rs_check_ast.h"
2011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
2111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_assert.h"
228024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet#include "slang.h"
23089cde338148fbb75825aea4539ccdae8211ffefStephen Hines#include "slang_rs_export_foreach.h"
24c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala#include "slang_rs_export_reduce.h"
2511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_rs_export_type.h"
2611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
2711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesnamespace slang {
2811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
2911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitStmt(clang::Stmt *S) {
3011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // This function does the actual iteration through all sub-Stmt's within
3111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // a given Stmt. Note that this function is skipped by all of the other
3211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // Visit* functions if we have already found a higher-level match.
3311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
3411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       I != E;
3511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       I++) {
3611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    if (clang::Stmt *Child = *I) {
3711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      Visit(Child);
3811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
3911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
4011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
4111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
42616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosservoid RSCheckAST::WarnOnSetElementAt(clang::CallExpr *E) {
43616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::FunctionDecl *Decl;
44616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  Decl = clang::dyn_cast_or_null<clang::FunctionDecl>(E->getCalleeDecl());
45616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
46616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (!Decl || Decl->getNameAsString() != std::string("rsSetElementAt")) {
47616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    return;
48616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
49616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
50616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::Expr *Expr;
51616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::ImplicitCastExpr *ImplCast;
52616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  Expr = E->getArg(1);
53616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  ImplCast = clang::dyn_cast_or_null<clang::ImplicitCastExpr>(Expr);
54616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
55616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (!ImplCast) {
56616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    return;
57616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
58616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
59616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const clang::Type *Ty;
60616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const clang::VectorType *VectorTy;
61616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const clang::BuiltinType *ElementTy;
62616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  Ty = ImplCast->getSubExpr()->getType()->getPointeeType()
63616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    ->getUnqualifiedDesugaredType();
64616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  VectorTy = clang::dyn_cast_or_null<clang::VectorType>(Ty);
65616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
66616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (VectorTy) {
67616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    ElementTy = clang::dyn_cast_or_null<clang::BuiltinType>(
68616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      VectorTy->getElementType()->getUnqualifiedDesugaredType());
69616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  } else {
70616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    ElementTy = clang::dyn_cast_or_null<clang::BuiltinType>(
71616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Ty->getUnqualifiedDesugaredType());
72616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
73616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
74616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (!ElementTy) {
75616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    return;
76616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
77616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
78616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  // We only support vectors with 2, 3 or 4 elements.
79616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (VectorTy) {
80616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    switch (VectorTy->getNumElements()) {
81616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    default:
82616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      return;
83616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case 2:
84616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case 3:
85616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case 4:
86616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
87616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    }
88616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
89616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
90616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const char *Name;
91616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
92616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  switch (ElementTy->getKind()) {
93616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Float:
94616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "float";
95616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
96616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Double:
97616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "double";
98616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
99616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Char_S:
100616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "char";
101616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
102616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Short:
103616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "short";
104616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
105616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Int:
106616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "int";
107616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
108616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Long:
109616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "long";
110616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
111616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::UChar:
112616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "uchar";
113616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
114616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::UShort:
115616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "ushort";
116616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
117616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::UInt:
118616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "uint";
119616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
120616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::ULong:
121616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "ulong";
122616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
123616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    default:
124616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      return;
125616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
126616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
127d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet  clang::DiagnosticBuilder DiagBuilder =
128d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet      Context->ReportWarning(E->getLocStart(),
129d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet                             "untyped rsSetElementAt() can reduce performance. "
130d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet                             "Use rsSetElementAt_%0%1() instead.");
131616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  DiagBuilder << Name;
132616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
133616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (VectorTy) {
134616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    DiagBuilder << VectorTy->getNumElements();
135616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  } else {
136616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    DiagBuilder << "";
137616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
138616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser}
139616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
140616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosservoid RSCheckAST::VisitCallExpr(clang::CallExpr *E) {
141616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  WarnOnSetElementAt(E);
142616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
143616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  for (clang::CallExpr::arg_iterator AI = E->arg_begin(), AE = E->arg_end();
144616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser       AI != AE; ++AI) {
145616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    Visit(*AI);
146616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
147616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser}
148616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
14911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateFunctionDecl(clang::FunctionDecl *FD) {
15011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (!FD) {
15111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    return;
15211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
15311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
154c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala  if (FD->hasAttr<clang::KernelAttr>()) {
155c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    // Validate that the kernel attribute is not used with static.
156c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    if (FD->getStorageClass() == clang::SC_Static) {
157c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      Context->ReportError(FD->getLocation(),
158c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala                           "Invalid use of attribute kernel with "
159c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala                           "static function declaration: %0")
160f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala        << FD->getName();
161c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      mValid = false;
162c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    }
163c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala
164c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    // We allow no arguments to the attribute, or an expected single
165c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    // argument. If there is an expected single argument, we verify
166c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    // that it is one of the recognized kernel kinds.
167c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    llvm::StringRef KernelKind =
168c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      FD->getAttr<clang::KernelAttr>()->getKernelKind();
169c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala
1708ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross    if (!KernelKind.empty()) {
171c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      Context->ReportError(FD->getLocation(),
172c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala                           "Unknown kernel attribute argument '%0' "
173c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala                           "in declaration of function '%1'")
174c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala        << KernelKind << FD->getName();
175c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala      mValid = false;
176c0c5dd85f2d2df2bcf0cb284001f544d6c42eff9Matt Wala    }
177f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala  }
178f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala
179ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  clang::QualType resultType = FD->getReturnType().getCanonicalType();
180ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  bool isExtern = (FD->getFormalLinkage() == clang::ExternalLinkage);
18111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
182ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  // We use FD as our NamedDecl in the case of a bad return type.
183ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  if (!RSExportType::ValidateType(Context, C, resultType, FD,
184ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines                                  FD->getLocStart(), mTargetAPI,
185ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines                                  mIsFilterscript, isExtern)) {
186ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines    mValid = false;
187ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  }
18811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
189ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  size_t numParams = FD->getNumParams();
190ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  for (size_t i = 0; i < numParams; i++) {
191ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines    clang::ParmVarDecl *PVD = FD->getParamDecl(i);
192ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines    clang::QualType QT = PVD->getType().getCanonicalType();
193ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines    if (!RSExportType::ValidateType(Context, C, QT, PVD, PVD->getLocStart(),
194ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines                                    mTargetAPI, mIsFilterscript, isExtern)) {
19511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      mValid = false;
19611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
19711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
19811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
199089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  bool saveKernel = mInKernel;
2008ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross  mInKernel = RSExportForEach::isRSForEachFunc(mTargetAPI, FD);
201089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
20211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (clang::Stmt *Body = FD->getBody()) {
20311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    Visit(Body);
20411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
205089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
206089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  mInKernel = saveKernel;
20711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
20811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
20911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
21011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateVarDecl(clang::VarDecl *VD) {
2115e306b944425a952fe744f59d828538137a59375David Gross  if (!VD || RSContext::isSyntheticName(VD->getName())) {
21211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    return;
21311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
21411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
215089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  clang::QualType QT = VD->getType();
21611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
21744f10063c2c08dab103a44cded0c3a288d65d43bStephen Hines  if (VD->getFormalLinkage() == clang::ExternalLinkage) {
21811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    llvm::StringRef TypeName;
219089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    const clang::Type *T = QT.getTypePtr();
22013fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines    if (!RSExportType::NormalizeType(T, TypeName, Context, VD,
22113fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines                                     NotLegacyKernelArgument)) {
22211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      mValid = false;
22311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
22411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
22511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
226089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  // We don't allow static (non-const) variables within kernels.
227089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  if (mInKernel && VD->isStaticLocal()) {
228089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    if (!QT.isConstQualified()) {
229d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet      Context->ReportError(
230d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet          VD->getLocation(),
231d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet          "Non-const static variables are not allowed in kernels: '%0'")
232089cde338148fbb75825aea4539ccdae8211ffefStephen Hines          << VD->getName();
233089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      mValid = false;
234089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    }
235089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  }
236089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
237d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet  if (!RSExportType::ValidateVarDecl(Context, VD, mTargetAPI, mIsFilterscript)) {
23811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    mValid = false;
23911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  } else if (clang::Expr *Init = VD->getInit()) {
24011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    // Only check the initializer if the decl is already ok.
24111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    Visit(Init);
24211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
24311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
24411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
24511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
24611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) {
2478024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet  if (!Slang::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) {
24811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    for (clang::DeclStmt::decl_iterator I = DS->decl_begin(),
24911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines                                        E = DS->decl_end();
25011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines         I != E;
25111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines         ++I) {
25211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I)) {
25311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateVarDecl(VD);
25411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::FunctionDecl *FD =
25511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines            llvm::dyn_cast<clang::FunctionDecl>(*I)) {
25611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateFunctionDecl(FD);
25711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      }
25811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
25911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
26011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
26111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
26211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
263dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hinesvoid RSCheckAST::VisitCastExpr(clang::CastExpr *CE) {
264dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  if (CE->getCastKind() == clang::CK_BitCast) {
265dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    clang::QualType QT = CE->getType();
266dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    const clang::Type *T = QT.getTypePtr();
267dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    if (T->isVectorType()) {
268dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      if (llvm::isa<clang::ImplicitCastExpr>(CE)) {
269d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet        Context->ReportError(CE->getExprLoc(), "invalid implicit vector cast");
270dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      } else {
271d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet        Context->ReportError(CE->getExprLoc(), "invalid vector cast");
272dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      }
273dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      mValid = false;
274dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    }
275dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  }
276dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  Visit(CE->getSubExpr());
277dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines}
278dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines
279dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines
28011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitExpr(clang::Expr *E) {
28111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // This is where FS checks for code using pointer and/or 64-bit expressions
28211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // (i.e. things like casts).
28311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
28411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // First we skip implicit casts (things like function calls and explicit
28511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // array accesses rely heavily on them and they are valid.
28611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  E = E->IgnoreImpCasts();
287ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines
288ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  // Expressions at this point in the checker are not externally visible.
289ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines  static const bool kIsExtern = false;
290ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines
29111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (mIsFilterscript &&
2928024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet      !Slang::IsLocInRSHeaderFile(E->getExprLoc(), mSM) &&
2935abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      !RSExportType::ValidateType(Context, C, E->getType(), nullptr, E->getExprLoc(),
294ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines                                  mTargetAPI, mIsFilterscript, kIsExtern)) {
29511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    mValid = false;
29611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  } else {
29711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    // Only visit sub-expressions if we haven't already seen a violation.
29811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    VisitStmt(E);
29911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
30011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
30111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
30211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
30311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesbool RSCheckAST::Validate() {
30411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
30511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
30611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines          DE = TUDecl->decls_end();
30711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       DI != DE;
30811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       DI++) {
3098024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet    if (!Slang::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) {
31011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) {
31111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateVarDecl(VD);
31211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::FunctionDecl *FD =
31311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines            llvm::dyn_cast<clang::FunctionDecl>(*DI)) {
31411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateFunctionDecl(FD);
31511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::Stmt *Body = (*DI)->getBody()) {
31611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        Visit(Body);
31711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      }
31811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
31911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
32011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
32111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  return mValid;
32211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
32311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
32411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}  // namespace slang
325