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 154b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar // Validate that the kernel attribute is not used with static. 155b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar if (FD->hasAttr<clang::RenderScriptKernelAttr>() && 156b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar FD->getStorageClass() == clang::SC_Static) { 157b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar Context->ReportError(FD->getLocation(), 158b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar "Invalid use of attribute kernel with " 159b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar "static function declaration: %0") 160b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar << FD->getName(); 161b6a143562bda2117824a0515c208504e9a2830f1Pirama Arumuga Nainar mValid = false; 162f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala } 163f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala 164ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines clang::QualType resultType = FD->getReturnType().getCanonicalType(); 165ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines bool isExtern = (FD->getFormalLinkage() == clang::ExternalLinkage); 16611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 167ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines // We use FD as our NamedDecl in the case of a bad return type. 168ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines if (!RSExportType::ValidateType(Context, C, resultType, FD, 169ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines FD->getLocStart(), mTargetAPI, 170ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mIsFilterscript, isExtern)) { 171ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mValid = false; 172ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines } 17311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 174ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines size_t numParams = FD->getNumParams(); 175ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines for (size_t i = 0; i < numParams; i++) { 176ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines clang::ParmVarDecl *PVD = FD->getParamDecl(i); 177ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 178ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines if (!RSExportType::ValidateType(Context, C, QT, PVD, PVD->getLocStart(), 179ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mTargetAPI, mIsFilterscript, isExtern)) { 18011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 18111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 18211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 18311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 184089cde338148fbb75825aea4539ccdae8211ffefStephen Hines bool saveKernel = mInKernel; 1858ee018bdb53fc5abdc430878e2bec0c0c0aa560fDavid Gross mInKernel = RSExportForEach::isRSForEachFunc(mTargetAPI, FD); 186089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 18711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::Stmt *Body = FD->getBody()) { 18811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 18911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 190089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 191089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mInKernel = saveKernel; 19211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 19311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 19411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 19511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateVarDecl(clang::VarDecl *VD) { 1965e306b944425a952fe744f59d828538137a59375David Gross if (!VD || RSContext::isSyntheticName(VD->getName())) { 19711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 19811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 19911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 200089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::QualType QT = VD->getType(); 20111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 20244f10063c2c08dab103a44cded0c3a288d65d43bStephen Hines if (VD->getFormalLinkage() == clang::ExternalLinkage) { 20311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::StringRef TypeName; 204089cde338148fbb75825aea4539ccdae8211ffefStephen Hines const clang::Type *T = QT.getTypePtr(); 20513fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines if (!RSExportType::NormalizeType(T, TypeName, Context, VD, 20613fad85b3c99a37c17d8acfec72f46b8ee64e912Stephen Hines NotLegacyKernelArgument)) { 20711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 20811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 20911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 21011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 211089cde338148fbb75825aea4539ccdae8211ffefStephen Hines // We don't allow static (non-const) variables within kernels. 212089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (mInKernel && VD->isStaticLocal()) { 213089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (!QT.isConstQualified()) { 214d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError( 215d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet VD->getLocation(), 216d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Non-const static variables are not allowed in kernels: '%0'") 217089cde338148fbb75825aea4539ccdae8211ffefStephen Hines << VD->getName(); 218089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mValid = false; 219089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 220089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 221089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 222d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet if (!RSExportType::ValidateVarDecl(Context, VD, mTargetAPI, mIsFilterscript)) { 22311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 22411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Expr *Init = VD->getInit()) { 22511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Only check the initializer if the decl is already ok. 22611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Init); 22711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 22811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 22911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 23011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 23111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) { 2328024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet if (!Slang::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) { 23311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), 23411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = DS->decl_end(); 23511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I != E; 23611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ++I) { 23711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I)) { 23811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 23911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 24011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*I)) { 24111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 24211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 24311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 24411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 24511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 24611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 24711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 248dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hinesvoid RSCheckAST::VisitCastExpr(clang::CastExpr *CE) { 249dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines if (CE->getCastKind() == clang::CK_BitCast) { 250dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines clang::QualType QT = CE->getType(); 251dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines const clang::Type *T = QT.getTypePtr(); 252dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines if (T->isVectorType()) { 253dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines if (llvm::isa<clang::ImplicitCastExpr>(CE)) { 254d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(CE->getExprLoc(), "invalid implicit vector cast"); 255dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } else { 256d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(CE->getExprLoc(), "invalid vector cast"); 257dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } 258dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines mValid = false; 259dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } 260dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } 261dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines Visit(CE->getSubExpr()); 262dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines} 263dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines 264dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines 26511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitExpr(clang::Expr *E) { 26611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // This is where FS checks for code using pointer and/or 64-bit expressions 26711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // (i.e. things like casts). 26811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 26911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // First we skip implicit casts (things like function calls and explicit 27011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // array accesses rely heavily on them and they are valid. 27111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = E->IgnoreImpCasts(); 272ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines 273ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines // Expressions at this point in the checker are not externally visible. 274ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines static const bool kIsExtern = false; 275ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines 27611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (mIsFilterscript && 2778024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet !Slang::IsLocInRSHeaderFile(E->getExprLoc(), mSM) && 2785abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes !RSExportType::ValidateType(Context, C, E->getType(), nullptr, E->getExprLoc(), 279ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mTargetAPI, mIsFilterscript, kIsExtern)) { 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++) { 294b477c3549ac8c1ed6a07d1e92ec61877fbfd5e7cI-Jui (Ray) Sung 295b477c3549ac8c1ed6a07d1e92ec61877fbfd5e7cI-Jui (Ray) Sung // Following tests are not applicable to implicitly defined types 296b477c3549ac8c1ed6a07d1e92ec61877fbfd5e7cI-Jui (Ray) Sung if (DI->isImplicit()) 297b477c3549ac8c1ed6a07d1e92ec61877fbfd5e7cI-Jui (Ray) Sung continue; 298b477c3549ac8c1ed6a07d1e92ec61877fbfd5e7cI-Jui (Ray) Sung 2998024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet if (!Slang::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) { 30011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) { 30111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 30211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 30311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*DI)) { 30411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 30511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Stmt *Body = (*DI)->getBody()) { 30611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 30711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 30811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 30911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 31011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 31111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return mValid; 31211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 31311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 31411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} // namespace slang 315