slang_rs_check_ast.cpp revision 616854341745b958e0c409cdb6e21abb6225aa21
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
1711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_rs_check_ast.h"
1811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
1911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_assert.h"
2011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_rs.h"
21089cde338148fbb75825aea4539ccdae8211ffefStephen Hines#include "slang_rs_export_foreach.h"
2211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_rs_export_type.h"
2311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
2411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesnamespace slang {
2511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
2611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitStmt(clang::Stmt *S) {
2711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // This function does the actual iteration through all sub-Stmt's within
2811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // a given Stmt. Note that this function is skipped by all of the other
2911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // Visit* functions if we have already found a higher-level match.
3011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
3111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       I != E;
3211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       I++) {
3311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    if (clang::Stmt *Child = *I) {
3411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      Visit(Child);
3511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
3611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
3711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
3811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
39616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosservoid RSCheckAST::WarnOnSetElementAt(clang::CallExpr *E) {
40616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::FunctionDecl *Decl;
41616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
42616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  Decl = clang::dyn_cast_or_null<clang::FunctionDecl>(E->getCalleeDecl());
43616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
44616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (!Decl || Decl->getNameAsString() != std::string("rsSetElementAt")) {
45616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    return;
46616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
47616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
48616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::Expr *Expr;
49616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::ImplicitCastExpr *ImplCast;
50616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  Expr = E->getArg(1);
51616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  ImplCast = clang::dyn_cast_or_null<clang::ImplicitCastExpr>(Expr);
52616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
53616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (!ImplCast) {
54616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    return;
55616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
56616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
57616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const clang::Type *Ty;
58616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const clang::VectorType *VectorTy;
59616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const clang::BuiltinType *ElementTy;
60616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  Ty = ImplCast->getSubExpr()->getType()->getPointeeType()
61616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    ->getUnqualifiedDesugaredType();
62616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  VectorTy = clang::dyn_cast_or_null<clang::VectorType>(Ty);
63616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
64616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (VectorTy) {
65616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    ElementTy = clang::dyn_cast_or_null<clang::BuiltinType>(
66616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      VectorTy->getElementType()->getUnqualifiedDesugaredType());
67616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  } else {
68616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    ElementTy = clang::dyn_cast_or_null<clang::BuiltinType>(
69616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Ty->getUnqualifiedDesugaredType());
70616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
71616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
72616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (!ElementTy) {
73616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    return;
74616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
75616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
76616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  // We only support vectors with 2, 3 or 4 elements.
77616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (VectorTy) {
78616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    switch (VectorTy->getNumElements()) {
79616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    default:
80616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      return;
81616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case 2:
82616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case 3:
83616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case 4:
84616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
85616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    }
86616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
87616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
88616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  const char *Name;
89616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
90616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  switch (ElementTy->getKind()) {
91616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Float:
92616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "float";
93616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
94616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Double:
95616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "double";
96616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
97616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Char_S:
98616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "char";
99616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
100616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Short:
101616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "short";
102616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
103616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Int:
104616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "int";
105616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
106616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::Long:
107616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "long";
108616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
109616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::UChar:
110616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "uchar";
111616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
112616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::UShort:
113616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "ushort";
114616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
115616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::UInt:
116616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "uint";
117616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
118616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    case clang::BuiltinType::ULong:
119616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      Name = "ulong";
120616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      break;
121616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    default:
122616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser      return;
123616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
124616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
125616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  clang::DiagnosticBuilder DiagBuilder =  DiagEngine.Report(
126616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    clang::FullSourceLoc(E->getLocStart(), mSM),
127616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    mDiagEngine.getCustomDiagID( clang::DiagnosticsEngine::Warning,
128616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    "untyped rsSetElementAt() can reduce performance. "
129616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    "Use rsSetElementAt_%0%1() instead."));
130616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  DiagBuilder << Name;
131616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
132616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  if (VectorTy) {
133616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    DiagBuilder << VectorTy->getNumElements();
134616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  } else {
135616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    DiagBuilder << "";
136616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
137616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
138616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  return;
139616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser}
140616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
141616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosservoid RSCheckAST::VisitCallExpr(clang::CallExpr *E) {
142616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  WarnOnSetElementAt(E);
143616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
144616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  for (clang::CallExpr::arg_iterator AI = E->arg_begin(), AE = E->arg_end();
145616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser       AI != AE; ++AI) {
146616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser    Visit(*AI);
147616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser  }
148616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser}
149616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser
15011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateFunctionDecl(clang::FunctionDecl *FD) {
15111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (!FD) {
15211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    return;
15311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
15411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
155089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  if (mIsFilterscript) {
156089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    // Validate parameters for Filterscript.
157089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    size_t numParams = FD->getNumParams();
15811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
159089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    clang::QualType resultType = FD->getResultType().getCanonicalType();
16011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
161089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    // We use FD as our NamedDecl in the case of a bad return type.
162089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    if (!RSExportType::ValidateType(C, resultType, FD,
163089cde338148fbb75825aea4539ccdae8211ffefStephen Hines                                    FD->getLocStart(), mTargetAPI,
164089cde338148fbb75825aea4539ccdae8211ffefStephen Hines                                    mIsFilterscript)) {
16511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      mValid = false;
16611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
167089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
168089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    for (size_t i = 0; i < numParams; i++) {
169089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      clang::ParmVarDecl *PVD = FD->getParamDecl(i);
170089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      clang::QualType QT = PVD->getType().getCanonicalType();
171089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      if (!RSExportType::ValidateType(C, QT, PVD, PVD->getLocStart(),
172089cde338148fbb75825aea4539ccdae8211ffefStephen Hines                                      mTargetAPI, mIsFilterscript)) {
173089cde338148fbb75825aea4539ccdae8211ffefStephen Hines        mValid = false;
174089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      }
175089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    }
17611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
17711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
178089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  bool saveKernel = mInKernel;
179089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  mInKernel = RSExportForEach::isRSForEachFunc(mTargetAPI, &mDiagEngine, FD);
180089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
18111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (clang::Stmt *Body = FD->getBody()) {
18211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    Visit(Body);
18311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
184089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
185089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  mInKernel = saveKernel;
18611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
18711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
18811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
18911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateVarDecl(clang::VarDecl *VD) {
19011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (!VD) {
19111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    return;
19211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
19311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
194089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  clang::QualType QT = VD->getType();
19511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
19644f10063c2c08dab103a44cded0c3a288d65d43bStephen Hines  if (VD->getFormalLinkage() == clang::ExternalLinkage) {
19711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    llvm::StringRef TypeName;
198089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    const clang::Type *T = QT.getTypePtr();
19911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    if (!RSExportType::NormalizeType(T, TypeName, &mDiagEngine, VD)) {
20011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      mValid = false;
20111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
20211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
20311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
204089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  // We don't allow static (non-const) variables within kernels.
205089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  if (mInKernel && VD->isStaticLocal()) {
206089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    if (!QT.isConstQualified()) {
207089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      mDiagEngine.Report(
208089cde338148fbb75825aea4539ccdae8211ffefStephen Hines        clang::FullSourceLoc(VD->getLocation(), mSM),
209089cde338148fbb75825aea4539ccdae8211ffefStephen Hines        mDiagEngine.getCustomDiagID(
210089cde338148fbb75825aea4539ccdae8211ffefStephen Hines          clang::DiagnosticsEngine::Error,
211089cde338148fbb75825aea4539ccdae8211ffefStephen Hines          "Non-const static variables are not allowed in kernels: '%0'"))
212089cde338148fbb75825aea4539ccdae8211ffefStephen Hines          << VD->getName();
213089cde338148fbb75825aea4539ccdae8211ffefStephen Hines      mValid = false;
214089cde338148fbb75825aea4539ccdae8211ffefStephen Hines    }
215089cde338148fbb75825aea4539ccdae8211ffefStephen Hines  }
216089cde338148fbb75825aea4539ccdae8211ffefStephen Hines
21711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (!RSExportType::ValidateVarDecl(VD, mTargetAPI, mIsFilterscript)) {
21811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    mValid = false;
21911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  } else if (clang::Expr *Init = VD->getInit()) {
22011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    // Only check the initializer if the decl is already ok.
22111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    Visit(Init);
22211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
22311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
22411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
22511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
22611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) {
22711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (!SlangRS::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) {
22811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    for (clang::DeclStmt::decl_iterator I = DS->decl_begin(),
22911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines                                        E = DS->decl_end();
23011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines         I != E;
23111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines         ++I) {
23211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I)) {
23311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateVarDecl(VD);
23411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::FunctionDecl *FD =
23511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines            llvm::dyn_cast<clang::FunctionDecl>(*I)) {
23611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateFunctionDecl(FD);
23711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      }
23811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
23911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
24011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
24111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
24211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
243dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hinesvoid RSCheckAST::VisitCastExpr(clang::CastExpr *CE) {
244dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  if (CE->getCastKind() == clang::CK_BitCast) {
245dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    clang::QualType QT = CE->getType();
246dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    const clang::Type *T = QT.getTypePtr();
247dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    if (T->isVectorType()) {
248dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
249dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      if (llvm::isa<clang::ImplicitCastExpr>(CE)) {
250dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines        DiagEngine.Report(
251dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          clang::FullSourceLoc(CE->getExprLoc(),
252dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                               DiagEngine.getSourceManager()),
253dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
254dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                                     "invalid implicit vector cast"));
255dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      } else {
256dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines        DiagEngine.Report(
257dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          clang::FullSourceLoc(CE->getExprLoc(),
258dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                               DiagEngine.getSourceManager()),
259dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
260dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                                     "invalid vector cast"));
261dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      }
262dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      mValid = false;
263dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    }
264dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  }
265dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  Visit(CE->getSubExpr());
266dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines}
267dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines
268dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines
26911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitExpr(clang::Expr *E) {
27011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // This is where FS checks for code using pointer and/or 64-bit expressions
27111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // (i.e. things like casts).
27211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
27311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // First we skip implicit casts (things like function calls and explicit
27411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // array accesses rely heavily on them and they are valid.
27511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  E = E->IgnoreImpCasts();
27611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (mIsFilterscript &&
27711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      !SlangRS::IsLocInRSHeaderFile(E->getExprLoc(), mSM) &&
27811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      !RSExportType::ValidateType(C, E->getType(), NULL, E->getExprLoc(),
27911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines                                  mTargetAPI, mIsFilterscript)) {
28011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    mValid = false;
28111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  } else {
28211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    // Only visit sub-expressions if we haven't already seen a violation.
28311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    VisitStmt(E);
28411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
28511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
28611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
28711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
28811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesbool RSCheckAST::Validate() {
28911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
29011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
29111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines          DE = TUDecl->decls_end();
29211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       DI != DE;
29311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       DI++) {
29411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    if (!SlangRS::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) {
29511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) {
29611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateVarDecl(VD);
29711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::FunctionDecl *FD =
29811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines            llvm::dyn_cast<clang::FunctionDecl>(*DI)) {
29911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateFunctionDecl(FD);
30011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::Stmt *Body = (*DI)->getBody()) {
30111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        Visit(Body);
30211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      }
30311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
30411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
30511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
30611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  return mValid;
30711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
30811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
30911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}  // namespace slang
310