slang_rs_check_ast.cpp revision f5b882cc561f656eb650d0fa6db7bac57989ab12
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" 2411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_rs_export_type.h" 2511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 2611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesnamespace slang { 2711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 2811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitStmt(clang::Stmt *S) { 2911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // This function does the actual iteration through all sub-Stmt's within 3011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // a given Stmt. Note that this function is skipped by all of the other 3111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Visit* functions if we have already found a higher-level match. 3211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 3311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I != E; 3411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I++) { 3511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::Stmt *Child = *I) { 3611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Child); 3711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 3811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 3911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 4011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 41616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosservoid RSCheckAST::WarnOnSetElementAt(clang::CallExpr *E) { 42616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser clang::FunctionDecl *Decl; 43616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Decl = clang::dyn_cast_or_null<clang::FunctionDecl>(E->getCalleeDecl()); 44616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 45616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser if (!Decl || Decl->getNameAsString() != std::string("rsSetElementAt")) { 46616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser return; 47616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 48616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 49616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser clang::Expr *Expr; 50616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser clang::ImplicitCastExpr *ImplCast; 51616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Expr = E->getArg(1); 52616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser ImplCast = clang::dyn_cast_or_null<clang::ImplicitCastExpr>(Expr); 53616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 54616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser if (!ImplCast) { 55616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser return; 56616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 57616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 58616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser const clang::Type *Ty; 59616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser const clang::VectorType *VectorTy; 60616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser const clang::BuiltinType *ElementTy; 61616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Ty = ImplCast->getSubExpr()->getType()->getPointeeType() 62616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser ->getUnqualifiedDesugaredType(); 63616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser VectorTy = clang::dyn_cast_or_null<clang::VectorType>(Ty); 64616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 65616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser if (VectorTy) { 66616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser ElementTy = clang::dyn_cast_or_null<clang::BuiltinType>( 67616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser VectorTy->getElementType()->getUnqualifiedDesugaredType()); 68616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } else { 69616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser ElementTy = clang::dyn_cast_or_null<clang::BuiltinType>( 70616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Ty->getUnqualifiedDesugaredType()); 71616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 72616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 73616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser if (!ElementTy) { 74616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser return; 75616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 76616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 77616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser // We only support vectors with 2, 3 or 4 elements. 78616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser if (VectorTy) { 79616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser switch (VectorTy->getNumElements()) { 80616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser default: 81616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser return; 82616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case 2: 83616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case 3: 84616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case 4: 85616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 86616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 87616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 88616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 89616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser const char *Name; 90616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 91616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser switch (ElementTy->getKind()) { 92616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::Float: 93616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "float"; 94616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 95616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::Double: 96616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "double"; 97616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 98616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::Char_S: 99616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "char"; 100616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 101616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::Short: 102616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "short"; 103616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 104616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::Int: 105616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "int"; 106616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 107616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::Long: 108616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "long"; 109616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 110616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::UChar: 111616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "uchar"; 112616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 113616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::UShort: 114616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "ushort"; 115616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 116616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::UInt: 117616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "uint"; 118616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 119616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser case clang::BuiltinType::ULong: 120616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Name = "ulong"; 121616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser break; 122616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser default: 123616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser return; 124616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 125616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 126d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet clang::DiagnosticBuilder DiagBuilder = 127d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportWarning(E->getLocStart(), 128d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "untyped rsSetElementAt() can reduce performance. " 129d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "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 139616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosservoid RSCheckAST::VisitCallExpr(clang::CallExpr *E) { 140616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser WarnOnSetElementAt(E); 141616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 142616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser for (clang::CallExpr::arg_iterator AI = E->arg_begin(), AE = E->arg_end(); 143616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser AI != AE; ++AI) { 144616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser Visit(*AI); 145616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser } 146616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser} 147616854341745b958e0c409cdb6e21abb6225aa21Tobias Grosser 14811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateFunctionDecl(clang::FunctionDecl *FD) { 14911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!FD) { 15011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 15111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 15211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 153f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala // Validate that the kernel attribute is not used with static. 154f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala if (FD->hasAttr<clang::KernelAttr>() && 155f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala FD->getStorageClass() == clang::SC_Static) { 156f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala Context->ReportError(FD->getLocation(), 157f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala "Invalid use of attribute kernel with " 158f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala "static function declaration: %0") 159f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala << FD->getName(); 160f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala mValid = false; 161f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala } 162f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala 163ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines clang::QualType resultType = FD->getReturnType().getCanonicalType(); 164ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines bool isExtern = (FD->getFormalLinkage() == clang::ExternalLinkage); 16511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 166ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines // We use FD as our NamedDecl in the case of a bad return type. 167ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines if (!RSExportType::ValidateType(Context, C, resultType, FD, 168ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines FD->getLocStart(), mTargetAPI, 169ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mIsFilterscript, isExtern)) { 170ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mValid = false; 171ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines } 17211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 173ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines size_t numParams = FD->getNumParams(); 174ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines for (size_t i = 0; i < numParams; i++) { 175ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines clang::ParmVarDecl *PVD = FD->getParamDecl(i); 176ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 177ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines if (!RSExportType::ValidateType(Context, C, QT, PVD, PVD->getLocStart(), 178ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mTargetAPI, mIsFilterscript, isExtern)) { 17911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 18011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 18111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 18211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 183089cde338148fbb75825aea4539ccdae8211ffefStephen Hines bool saveKernel = mInKernel; 184f5b882cc561f656eb650d0fa6db7bac57989ab12Matt Wala mInKernel = RSExportForEach::isRSForEachFunc(mTargetAPI, FD); 185089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 18611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::Stmt *Body = FD->getBody()) { 18711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 18811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 189089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 190089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mInKernel = saveKernel; 19111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 19211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 19311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 19411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateVarDecl(clang::VarDecl *VD) { 19511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!VD) { 19611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 19711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 19811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 199089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::QualType QT = VD->getType(); 20011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 20144f10063c2c08dab103a44cded0c3a288d65d43bStephen Hines if (VD->getFormalLinkage() == clang::ExternalLinkage) { 20211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::StringRef TypeName; 203089cde338148fbb75825aea4539ccdae8211ffefStephen Hines const clang::Type *T = QT.getTypePtr(); 20448d893dc7794b3cfb74f35955ca763ee4170f9adStephen Hines if (!RSExportType::NormalizeType(T, TypeName, Context, VD)) { 20511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 20611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 20711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 20811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 209089cde338148fbb75825aea4539ccdae8211ffefStephen Hines // We don't allow static (non-const) variables within kernels. 210089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (mInKernel && VD->isStaticLocal()) { 211089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (!QT.isConstQualified()) { 212d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError( 213d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet VD->getLocation(), 214d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet "Non-const static variables are not allowed in kernels: '%0'") 215089cde338148fbb75825aea4539ccdae8211ffefStephen Hines << VD->getName(); 216089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mValid = false; 217089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 218089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 219089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 220d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet if (!RSExportType::ValidateVarDecl(Context, VD, mTargetAPI, mIsFilterscript)) { 22111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 22211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Expr *Init = VD->getInit()) { 22311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Only check the initializer if the decl is already ok. 22411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Init); 22511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 22611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 22711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 22811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 22911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) { 2308024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet if (!Slang::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) { 23111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), 23211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = DS->decl_end(); 23311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I != E; 23411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ++I) { 23511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I)) { 23611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 23711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 23811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*I)) { 23911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 24011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 24111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 24211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 24311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 24411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 24511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 246dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hinesvoid RSCheckAST::VisitCastExpr(clang::CastExpr *CE) { 247dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines if (CE->getCastKind() == clang::CK_BitCast) { 248dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines clang::QualType QT = CE->getType(); 249dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines const clang::Type *T = QT.getTypePtr(); 250dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines if (T->isVectorType()) { 251dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines if (llvm::isa<clang::ImplicitCastExpr>(CE)) { 252d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(CE->getExprLoc(), "invalid implicit vector cast"); 253dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } else { 254d3f7527b105d21f1c69d3473eb88a762f2c3ab5aJean-Luc Brouillet Context->ReportError(CE->getExprLoc(), "invalid vector cast"); 255dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } 256dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines mValid = false; 257dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } 258dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines } 259dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines Visit(CE->getSubExpr()); 260dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines} 261dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines 262dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines 26311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitExpr(clang::Expr *E) { 26411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // This is where FS checks for code using pointer and/or 64-bit expressions 26511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // (i.e. things like casts). 26611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 26711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // First we skip implicit casts (things like function calls and explicit 26811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // array accesses rely heavily on them and they are valid. 26911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = E->IgnoreImpCasts(); 270ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines 271ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines // Expressions at this point in the checker are not externally visible. 272ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines static const bool kIsExtern = false; 273ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines 27411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (mIsFilterscript && 2758024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet !Slang::IsLocInRSHeaderFile(E->getExprLoc(), mSM) && 2765abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes !RSExportType::ValidateType(Context, C, E->getType(), nullptr, E->getExprLoc(), 277ab94bccca64c9b126cbd1b732aa5e681d8639b99Stephen Hines mTargetAPI, mIsFilterscript, kIsExtern)) { 27811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 27911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else { 28011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Only visit sub-expressions if we haven't already seen a violation. 28111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines VisitStmt(E); 28211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 28311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 28411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 28511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 28611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesbool RSCheckAST::Validate() { 28711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 28811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(), 28911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DE = TUDecl->decls_end(); 29011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DI != DE; 29111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DI++) { 2928024ed54c23c08534434da14d3be99c3efcc5754Jean-Luc Brouillet if (!Slang::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) { 29311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) { 29411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 29511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 29611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*DI)) { 29711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 29811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Stmt *Body = (*DI)->getBody()) { 29911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 30011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 30111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 30211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 30311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 30411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return mValid; 30511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 30611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 30711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} // namespace slang 308