slang_rs_check_ast.cpp revision 089cde338148fbb75825aea4539ccdae8211ffef
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 3911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateFunctionDecl(clang::FunctionDecl *FD) { 4011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!FD) { 4111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 4211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 4311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 44089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (mIsFilterscript) { 45089cde338148fbb75825aea4539ccdae8211ffefStephen Hines // Validate parameters for Filterscript. 46089cde338148fbb75825aea4539ccdae8211ffefStephen Hines size_t numParams = FD->getNumParams(); 4711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 48089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::QualType resultType = FD->getResultType().getCanonicalType(); 4911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 50089cde338148fbb75825aea4539ccdae8211ffefStephen Hines // We use FD as our NamedDecl in the case of a bad return type. 51089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (!RSExportType::ValidateType(C, resultType, FD, 52089cde338148fbb75825aea4539ccdae8211ffefStephen Hines FD->getLocStart(), mTargetAPI, 53089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mIsFilterscript)) { 5411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 5511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 56089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 57089cde338148fbb75825aea4539ccdae8211ffefStephen Hines for (size_t i = 0; i < numParams; i++) { 58089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::ParmVarDecl *PVD = FD->getParamDecl(i); 59089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 60089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (!RSExportType::ValidateType(C, QT, PVD, PVD->getLocStart(), 61089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mTargetAPI, mIsFilterscript)) { 62089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mValid = false; 63089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 64089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 6511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 6611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 67089cde338148fbb75825aea4539ccdae8211ffefStephen Hines bool saveKernel = mInKernel; 68089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mInKernel = RSExportForEach::isRSForEachFunc(mTargetAPI, &mDiagEngine, FD); 69089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 7011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::Stmt *Body = FD->getBody()) { 7111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 7211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 73089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 74089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mInKernel = saveKernel; 7511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 7611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 7711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 7811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateVarDecl(clang::VarDecl *VD) { 7911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!VD) { 8011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 8111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 8211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 83089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::QualType QT = VD->getType(); 8411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 8511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (VD->getLinkage() == clang::ExternalLinkage) { 8611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::StringRef TypeName; 87089cde338148fbb75825aea4539ccdae8211ffefStephen Hines const clang::Type *T = QT.getTypePtr(); 8811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!RSExportType::NormalizeType(T, TypeName, &mDiagEngine, VD)) { 8911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 9011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 9111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 9211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 93089cde338148fbb75825aea4539ccdae8211ffefStephen Hines // We don't allow static (non-const) variables within kernels. 94089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (mInKernel && VD->isStaticLocal()) { 95089cde338148fbb75825aea4539ccdae8211ffefStephen Hines if (!QT.isConstQualified()) { 96089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mDiagEngine.Report( 97089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::FullSourceLoc(VD->getLocation(), mSM), 98089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mDiagEngine.getCustomDiagID( 99089cde338148fbb75825aea4539ccdae8211ffefStephen Hines clang::DiagnosticsEngine::Error, 100089cde338148fbb75825aea4539ccdae8211ffefStephen Hines "Non-const static variables are not allowed in kernels: '%0'")) 101089cde338148fbb75825aea4539ccdae8211ffefStephen Hines << VD->getName(); 102089cde338148fbb75825aea4539ccdae8211ffefStephen Hines mValid = false; 103089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 104089cde338148fbb75825aea4539ccdae8211ffefStephen Hines } 105089cde338148fbb75825aea4539ccdae8211ffefStephen Hines 10611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!RSExportType::ValidateVarDecl(VD, mTargetAPI, mIsFilterscript)) { 10711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 10811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Expr *Init = VD->getInit()) { 10911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Only check the initializer if the decl is already ok. 11011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Init); 11111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 11211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 11311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 11411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 11511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) { 11611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!SlangRS::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) { 11711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), 11811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = DS->decl_end(); 11911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I != E; 12011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ++I) { 12111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I)) { 12211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 12311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 12411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*I)) { 12511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 12611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 12711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 12811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 12911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 13011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 13111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 13211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitExpr(clang::Expr *E) { 13311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // This is where FS checks for code using pointer and/or 64-bit expressions 13411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // (i.e. things like casts). 13511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 13611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // First we skip implicit casts (things like function calls and explicit 13711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // array accesses rely heavily on them and they are valid. 13811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = E->IgnoreImpCasts(); 13911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (mIsFilterscript && 14011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines !SlangRS::IsLocInRSHeaderFile(E->getExprLoc(), mSM) && 14111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines !RSExportType::ValidateType(C, E->getType(), NULL, E->getExprLoc(), 14211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mTargetAPI, mIsFilterscript)) { 14311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 14411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else { 14511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Only visit sub-expressions if we haven't already seen a violation. 14611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines VisitStmt(E); 14711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 14811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 14911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 15011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 15111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesbool RSCheckAST::Validate() { 15211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 15311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(), 15411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DE = TUDecl->decls_end(); 15511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DI != DE; 15611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DI++) { 15711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!SlangRS::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) { 15811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) { 15911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 16011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 16111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*DI)) { 16211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 16311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Stmt *Body = (*DI)->getBody()) { 16411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 16511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 16611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 16711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 16811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 16911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return mValid; 17011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 17111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 17211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} // namespace slang 173