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