slang_rs_check_ast.cpp revision dbb6dc37c377f8dd183f2069a6e27610d1202d98
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
132dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hinesvoid RSCheckAST::VisitCastExpr(clang::CastExpr *CE) {
133dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  if (CE->getCastKind() == clang::CK_BitCast) {
134dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    clang::QualType QT = CE->getType();
135dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    const clang::Type *T = QT.getTypePtr();
136dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    if (T->isVectorType()) {
137dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
138dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      if (llvm::isa<clang::ImplicitCastExpr>(CE)) {
139dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines        DiagEngine.Report(
140dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          clang::FullSourceLoc(CE->getExprLoc(),
141dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                               DiagEngine.getSourceManager()),
142dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
143dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                                     "invalid implicit vector cast"));
144dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      } else {
145dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines        DiagEngine.Report(
146dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          clang::FullSourceLoc(CE->getExprLoc(),
147dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                               DiagEngine.getSourceManager()),
148dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines          DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
149dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines                                     "invalid vector cast"));
150dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      }
151dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines      mValid = false;
152dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines    }
153dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  }
154dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines  Visit(CE->getSubExpr());
155dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines}
156dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines
157dbb6dc37c377f8dd183f2069a6e27610d1202d98Stephen Hines
15811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesvoid RSCheckAST::VisitExpr(clang::Expr *E) {
15911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // This is where FS checks for code using pointer and/or 64-bit expressions
16011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // (i.e. things like casts).
16111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
16211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // First we skip implicit casts (things like function calls and explicit
16311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  // array accesses rely heavily on them and they are valid.
16411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  E = E->IgnoreImpCasts();
16511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  if (mIsFilterscript &&
16611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      !SlangRS::IsLocInRSHeaderFile(E->getExprLoc(), mSM) &&
16711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      !RSExportType::ValidateType(C, E->getType(), NULL, E->getExprLoc(),
16811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines                                  mTargetAPI, mIsFilterscript)) {
16911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    mValid = false;
17011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  } else {
17111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    // Only visit sub-expressions if we haven't already seen a violation.
17211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    VisitStmt(E);
17311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
17411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
17511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
17611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
17711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hinesbool RSCheckAST::Validate() {
17811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
17911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
18011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines          DE = TUDecl->decls_end();
18111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       DI != DE;
18211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines       DI++) {
18311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    if (!SlangRS::IsLocInRSHeaderFile(DI->getLocStart(), mSM)) {
18411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      if (clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI)) {
18511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateVarDecl(VD);
18611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::FunctionDecl *FD =
18711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines            llvm::dyn_cast<clang::FunctionDecl>(*DI)) {
18811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        ValidateFunctionDecl(FD);
18911274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      } else if (clang::Stmt *Body = (*DI)->getBody()) {
19011274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines        Visit(Body);
19111274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines      }
19211274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines    }
19311274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  }
19411274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
19511274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines  return mValid;
19611274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}
19711274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines
19811274a7324b478ec13e1d10a1b81350b34a65ab1Stephen Hines}  // namespace slang
199