slang_rs_check_ast.cpp revision 11274a7324b478ec13e1d10a1b81350b34a65ab1
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" 2111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines#include "slang_rs_export_type.h" 2211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 2311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesnamespace slang { 2411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 2511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitStmt(clang::Stmt *S) { 2611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // This function does the actual iteration through all sub-Stmt's within 2711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // a given Stmt. Note that this function is skipped by all of the other 2811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Visit* functions if we have already found a higher-level match. 2911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 3011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I != E; 3111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I++) { 3211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::Stmt *Child = *I) { 3311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Child); 3411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 3511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 3611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 3711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 3811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateFunctionDecl(clang::FunctionDecl *FD) { 3911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!FD) { 4011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 4111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 4211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 4311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!mIsFilterscript) { 4411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // No additional validation for non-Filterscript functions. 4511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::Stmt *Body = FD->getBody()) { 4611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 4711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 4811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 4911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 5011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 5111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines size_t numParams = FD->getNumParams(); 5211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 5311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines clang::QualType resultType = FD->getResultType().getCanonicalType(); 5411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 5511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // We use FD as our NamedDecl in the case of a bad return type. 5611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!RSExportType::ValidateType(C, resultType, FD, 5711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines FD->getLocStart(), mTargetAPI, 5811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mIsFilterscript)) { 5911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 6011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 6111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 6211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (size_t i = 0; i < numParams; i++) { 6311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines clang::ParmVarDecl *PVD = FD->getParamDecl(i); 6411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines clang::QualType QT = PVD->getType().getCanonicalType(); 6511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!RSExportType::ValidateType(C, QT, PVD, PVD->getLocStart(), 6611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mTargetAPI, mIsFilterscript)) { 6711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 6811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 6911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 7011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 7111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::Stmt *Body = FD->getBody()) { 7211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 7311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 7411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 7511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 7611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 7711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::ValidateVarDecl(clang::VarDecl *VD) { 7811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!VD) { 7911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return; 8011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 8111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 8211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines const clang::Type *T = VD->getType().getTypePtr(); 8311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 8411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (VD->getLinkage() == clang::ExternalLinkage) { 8511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::StringRef TypeName; 8611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!RSExportType::NormalizeType(T, TypeName, &mDiagEngine, VD)) { 8711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 8811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 8911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 9011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 9111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!RSExportType::ValidateVarDecl(VD, mTargetAPI, mIsFilterscript)) { 9211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 9311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Expr *Init = VD->getInit()) { 9411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Only check the initializer if the decl is already ok. 9511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Init); 9611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 9711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 9811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 9911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 10011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitDeclStmt(clang::DeclStmt *DS) { 10111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!SlangRS::IsLocInRSHeaderFile(DS->getLocStart(), mSM)) { 10211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), 10311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = DS->decl_end(); 10411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines I != E; 10511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ++I) { 10611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I)) { 10711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 10811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 10911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*I)) { 11011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 11111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 11211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 11311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 11411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 11511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 11611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 11711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitExpr(clang::Expr *E) { 11811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // This is where FS checks for code using pointer and/or 64-bit expressions 11911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // (i.e. things like casts). 12011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 12111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // First we skip implicit casts (things like function calls and explicit 12211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // array accesses rely heavily on them and they are valid. 12311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines E = E->IgnoreImpCasts(); 12411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (mIsFilterscript && 12511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines !SlangRS::IsLocInRSHeaderFile(E->getExprLoc(), mSM) && 12611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines !RSExportType::ValidateType(C, E->getType(), NULL, E->getExprLoc(), 12711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mTargetAPI, mIsFilterscript)) { 12811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines mValid = false; 12911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else { 13011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines // Only visit sub-expressions if we haven't already seen a violation. 13111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines VisitStmt(E); 13211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 13311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 13411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 13511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 13611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesbool RSCheckAST::Validate() { 13711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 13811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(), 13911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DE = TUDecl->decls_end(); 14011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DI != DE; 14111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines DI++) { 14211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (!SlangRS::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) { 14311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) { 14411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateVarDecl(VD); 14511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::FunctionDecl *FD = 14611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines llvm::dyn_cast<clang::FunctionDecl>(*DI)) { 14711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines ValidateFunctionDecl(FD); 14811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } else if (clang::Stmt *Body = (*DI)->getBody()) { 14911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines Visit(Body); 15011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 15111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 15211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines } 15311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 15411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines return mValid; 15511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} 15611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines 15711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines} // namespace slang 158