void MisplacedOperatorInStrlenInAllocCheck::registerMatchers( MatchFinder *Finder) { const auto StrLenFunc = functionDecl(anyOf( hasName("::strlen"), hasName("::std::strlen"), hasName("::strnlen"), hasName("::std::strnlen"), hasName("::strnlen_s"), hasName("::std::strnlen_s"), hasName("::wcslen"), hasName("::std::wcslen"), hasName("::wcsnlen"), hasName("::std::wcsnlen"), hasName("::wcsnlen_s"), hasName("std::wcsnlen_s"))); const auto BadUse = callExpr(callee(StrLenFunc), hasAnyArgument(ignoringImpCasts( binaryOperator( hasOperatorName("+"), hasRHS(ignoringParenImpCasts(integerLiteral(equals(1))))) .bind("BinOp")))) .bind("StrLen"); const auto BadArg = anyOf( allOf(unless(binaryOperator( hasOperatorName("+"), hasLHS(BadUse), hasRHS(ignoringParenImpCasts(integerLiteral(equals(1)))))), hasDescendant(BadUse)), BadUse); const auto Alloc0Func = functionDecl(anyOf(hasName("::malloc"), hasName("std::malloc"), hasName("::alloca"), hasName("std::alloca"))); const auto Alloc1Func = functionDecl(anyOf(hasName("::calloc"), hasName("std::calloc"), hasName("::realloc"), hasName("std::realloc"))); const auto Alloc0FuncPtr = varDecl(hasType(isConstQualified()), hasInitializer(ignoringParenImpCasts( declRefExpr(hasDeclaration(Alloc0Func))))); const auto Alloc1FuncPtr = varDecl(hasType(isConstQualified()), hasInitializer(ignoringParenImpCasts( declRefExpr(hasDeclaration(Alloc1Func))))); Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))), hasArgument(0, BadArg)) .bind("Alloc"), this); Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))), hasArgument(1, BadArg)) .bind("Alloc"), this); Finder->addMatcher( cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this); }
void DefinitionsInHeadersCheck::registerMatchers(MatchFinder *Finder) { if (UseHeaderFileExtension) { Finder->addMatcher( namedDecl(anyOf(functionDecl(isDefinition()), varDecl(isDefinition())), isHeaderFileExtension()).bind("name-decl"), this); } else { Finder->addMatcher( namedDecl(anyOf(functionDecl(isDefinition()), varDecl(isDefinition())), anyOf(isHeaderFileExtension(), unless(isExpansionInMainFile()))).bind("name-decl"), this); } }
// compoundStmt ::= '{' varDecl* stmt* '}' std::unique_ptr<Stmt> FlowParser::compoundStmt() { FNTRACE(); FlowLocation sloc(location()); nextToken(); // '{' std::unique_ptr<CompoundStmt> cs = std::make_unique<CompoundStmt>(sloc); while (token() == FlowToken::Var) { if (std::unique_ptr<Variable> var = varDecl()) scope()->appendSymbol(std::move(var)); else return nullptr; } for (;;) { if (consumeIf(FlowToken::End)) { cs->location().update(end()); return std::unique_ptr<Stmt>(cs.release()); } if (std::unique_ptr<Stmt> s = stmt()) cs->push_back(std::move(s)); else return nullptr; } }
void block(int pIndex) /* pIndex はこのブロックの関数名のインデックス */ { int backP; backP = genCodeV(jmp, 0); /* 内部関数を飛び越す命令、後でバックパッチ */ while (1) { /* 宣言部のコンパイルを繰り返す */ switch (token.kind){ case Const: /* 定数宣言部のコンパイル */ token = nextToken(); constDecl(); continue; case Var: /* 変数宣言部のコンパイル */ token = nextToken(); varDecl(); continue; case Func: /* 関数宣言部のコンパイル */ token = nextToken(); funcDecl(); continue; default: /* それ以外なら宣言部は終わり */ break; } break; } backPatch(backP); /* 内部関数を飛び越す命令にパッチ */ changeV(pIndex, nextCode()); /* この関数の開始番地を修正 */ genCodeV(ict, frameL()); /* このブロックの実行時の必要記憶域をとる命令 */ statement(); /* このブロックの主文 */ genCodeR(); /* リターン命令 */ blockEnd(); /* ブロックが終ったことをtableに連絡 */ }
vector<string> CodeGenerator::block(vector<Node>::iterator& it) { vector<string> blockCode; ++it; ++it; while (it->symbol == "VarDeclList") { ++it; if (it->symbol == "VarDecl") { appendVectors(blockCode, varDecl(it)); ++it; } } ++it; while (it->symbol == "StmtList") { ++it; appendVectors(blockCode, statement(it)); it += 2; } ++it; // cout << "block " << it->symbol << endl; return blockCode; }
void CodeGenerator::codeGeneration(vector<Node> parseTree) { // set up print function llvmCode.push_back("@istr = private constant[4 x i8] c\"%d\\0A\\00\"\n"); llvmCode.push_back("@fstr = private constant[4 x i8] c\"%f\\0A\\00\"\n"); llvmCode.push_back("declare i32 @printf(i8*, ...)\n\n"); // scan the tree to generate the code for (vector<Node>::iterator it = parseTree.begin(); it != parseTree.end(); it++) { // Start analyzing the tree if (it->symbol == "DeclList'") // declaration of variable or function appendVectors(llvmCode, declaration(it)); else if (it->symbol == "VarDecl") // declaration of variable (could be array) appendVectors(llvmCode,varDecl(it)); else if (it->symbol == "Stmt") // statement is appeared appendVectors(llvmCode, statement(it)); else if (it->symbol == "{") { llvmCode.push_back("{\n"); instruction = 0; } else if (it->symbol == "}") llvmCode.push_back("}\n"); } exportLlvmCode(); }
int compile(char *fname) /* コンパイル */ { initChTyp(); /* 文字種表 */ gencode2(CALL, -1); /* main関数呼出。番地-1は仮設定 */ gencode1(STOP); /* プログラム終了 */ fileOpen(fname); token = nextTkn(); while (token.kind != EofTkn) { switch (token.kind) { case Int: case Void: /* 変数か関数 */ set_type(); set_name(); /* 型名と名前を格納 */ if (token.kind == '(') fncDecl(); else varDecl(); /* 関数,変数宣言 */ break; case Semicolon: token = nextTkn(); /* 何もせず次へ */ break; default: err_ss("構文エラー", token.text); token = nextTkn(); } } if (err_ct == 0) backPatch_callAdrs(); /* 関数呼出未定番地を後埋 */ *INT_P(mem_adrs(0)) = mallocG(0); /* 静的領域サイズを0番地に格納 */ if (err_ct > 0) fprintf(stderr, "%d個のエラーが発生しました。\n", err_ct); return err_ct == 0; /* エラーなしなら真 */ }
void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(functionDecl(parameterCountIs(0), unless(isImplicit()), unless(isExternC())) .bind(FunctionId), this); Finder->addMatcher(typedefNameDecl().bind(TypedefId), this); auto ParenFunctionType = parenType(innerType(functionType())); auto PointerToFunctionType = pointee(ParenFunctionType); auto FunctionOrMemberPointer = anyOf(hasType(pointerType(PointerToFunctionType)), hasType(memberPointerType(PointerToFunctionType))); Finder->addMatcher(fieldDecl(FunctionOrMemberPointer).bind(FieldId), this); Finder->addMatcher(varDecl(FunctionOrMemberPointer).bind(VarId), this); auto CastDestinationIsFunction = hasDestinationType(pointsTo(ParenFunctionType)); Finder->addMatcher( cStyleCastExpr(CastDestinationIsFunction).bind(CStyleCastId), this); Finder->addMatcher( cxxStaticCastExpr(CastDestinationIsFunction).bind(NamedCastId), this); Finder->addMatcher( cxxReinterpretCastExpr(CastDestinationIsFunction).bind(NamedCastId), this); Finder->addMatcher( cxxConstCastExpr(CastDestinationIsFunction).bind(NamedCastId), this); Finder->addMatcher(lambdaExpr().bind(LambdaId), this); }
void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) { const auto IsGlobal = allOf(hasGlobalStorage(), hasDeclContext(anyOf(translationUnitDecl(), // Global scope. namespaceDecl(), // Namespace scope. recordDecl())), // Class scope. unless(isConstexpr())); const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(IsGlobal, unless(isDefinition())).bind("referencee"))); Finder->addMatcher( varDecl(IsGlobal, isDefinition(), hasInitializer(expr(hasDescendant(ReferencesUndefinedGlobalVar)))) .bind("var"), this); }
void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()), varDecl(hasStaticStorageDuration()))), unless(isInTemplateInstantiation())) .bind("memberExpression"), this); }
void ScopeChecker::registerMatchers(MatchFinder *AstMatcher) { AstMatcher->addMatcher(varDecl().bind("node"), this); AstMatcher->addMatcher(cxxNewExpr().bind("node"), this); AstMatcher->addMatcher(materializeTemporaryExpr().bind("node"), this); AstMatcher->addMatcher( callExpr(callee(functionDecl(heapAllocator()))).bind("node"), this); AstMatcher->addMatcher(parmVarDecl().bind("parm_vardecl"), this); }
void petabricks::CodeGenerator::addMember(const std::string& type, const std::string& name, const std::string& initializer){ if(_curClass.size()>0){ //TODO for(ClassMembers::iterator i = _curMembers.begin(); i != _curMembers.end(); ++i) { JASSERT(i->type != type || i->name != name || i->initializer != initializer)(type)(name)(initializer); } ClassMember tmp; tmp.type=type; tmp.name=name; tmp.initializer=initializer; _curMembers.push_back(tmp); }else{ if(initializer.size()>0) varDecl(type+" "+name+" = "+initializer); else varDecl(type+" "+name); } }
IntrusiveRefCntPtr<VarDecl> Parser::declVar(string const& name, TypePtr type) { IntrusiveRefCntPtr<VarDecl> varDecl(new VarDecl(name, type)); varDecl->isParameter = false; currentScope->slots.push_back(varDecl); currentFunction->locals.push_back(varDecl); return varDecl; }
void Rule_18_7_1::registerMatchers(ast_matchers::MatchFinder *Finder) { Finder->addMatcher(callExpr(callee(functionDecl(anyOf(hasName("::signal"), hasName("::raise"))))) .bind("CallExpr"), this); Finder->addMatcher( varDecl(hasType(namedDecl(hasName("::sig_atomic_t")))).bind("VarDecl"), this); }
void Parser::statement(SeqExpr& seqExpr) { if(token == TLet) { varDecl(seqExpr, true); } else if(firstExpression[token]) { seqExpr.expressions.push_back(expression(true)); } }
std::unique_ptr<Symbol> FlowParser::decl() { FNTRACE(); switch (token()) { case FlowToken::Var: return varDecl(); case FlowToken::Handler: return handlerDecl(); default: return nullptr; } }
void block(int is_func) /* {}内の処理 */ { TknKind kd = Others; token = nextTkn(); ++blkNest; if (is_func) { /* 関数ブロックなら変数宣言処理 */ while (token.kind == Int) { set_type(); set_name(); varDecl(); } } while (token.kind != '}') { /* 文を処理 */ kd = token.kind; statement(); } last_statement = kd; /* 関数末尾のreturn有無確認に用いる */ --blkNest; token = nextTkn(); }
void StaticObjectExceptionCheck::registerMatchers(MatchFinder *Finder) { if ((!getLangOpts().CPlusPlus) || (!getLangOpts().CXXExceptions)) return; // Match any static or thread_local variable declaration that has an // initializer that can throw. Finder->addMatcher( varDecl(anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()), unless(anyOf(isConstexpr(), hasType(cxxRecordDecl(isLambda())), hasAncestor(functionDecl()))), anyOf(hasDescendant(cxxConstructExpr(hasDeclaration( cxxConstructorDecl(unless(isNoThrow())).bind("func")))), hasDescendant(cxxNewExpr(hasDeclaration( functionDecl(unless(isNoThrow())).bind("func")))), hasDescendant(callExpr(hasDeclaration( functionDecl(unless(isNoThrow())).bind("func")))))) .bind("var"), this); }
void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) { // Add parameters to Parameters. Finder->addMatcher(parmVarDecl(unless(isInstantiated())).bind("Parm"), this); // C++ constructor. Finder->addMatcher(cxxConstructorDecl().bind("Ctor"), this); // Track unused parameters, there is Wunused-parameter about unused // parameters. Finder->addMatcher(declRefExpr().bind("Ref"), this); // Analyse parameter usage in function. Finder->addMatcher(stmt(anyOf(unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--"))), binaryOperator(), callExpr(), returnStmt(), cxxConstructExpr())) .bind("Mark"), this); Finder->addMatcher(varDecl(hasInitializer(anything())).bind("Mark"), this); }
void DefinitionsInHeadersCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; auto DefinitionMatcher = anyOf(functionDecl(isDefinition(), unless(isDeleted())), varDecl(isDefinition())); if (UseHeaderFileExtension) { Finder->addMatcher(namedDecl(DefinitionMatcher, usesHeaderFileExtension(HeaderFileExtensions)) .bind("name-decl"), this); } else { Finder->addMatcher( namedDecl(DefinitionMatcher, anyOf(usesHeaderFileExtension(HeaderFileExtensions), unless(isExpansionInMainFile()))) .bind("name-decl"), this); } }
void StaticallyConstructedObjectsCheck::registerMatchers(MatchFinder *Finder) { // Constructing global, non-trivial objects with static storage is // disallowed, unless the object is statically initialized with a constexpr // constructor or has no explicit constructor. // Constexpr requires C++11 or later. if (!getLangOpts().CPlusPlus11) return; Finder->addMatcher(varDecl( // Match global, statically stored objects... isGlobalStatic(), // ... that have C++ constructors... hasDescendant(cxxConstructExpr(unless(allOf( // ... unless it is constexpr ... hasDeclaration(cxxConstructorDecl(isConstexpr())), // ... and is statically initialized. isConstantInitializer()))))) .bind("decl"), this); }
void MisplacedWideningCastCheck::registerMatchers(MatchFinder *Finder) { const auto Calc = expr(anyOf(binaryOperator( anyOf(hasOperatorName("+"), hasOperatorName("-"), hasOperatorName("*"), hasOperatorName("<<"))), unaryOperator(hasOperatorName("~"))), hasType(isInteger())) .bind("Calc"); const auto ExplicitCast = explicitCastExpr(hasDestinationType(isInteger()), has(ignoringParenImpCasts(Calc))); const auto ImplicitCast = implicitCastExpr(hasImplicitDestinationType(isInteger()), has(ignoringParenImpCasts(Calc))); const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast"); Finder->addMatcher(varDecl(hasInitializer(Cast)), this); Finder->addMatcher(returnStmt(hasReturnValue(Cast)), this); Finder->addMatcher(callExpr(hasAnyArgument(Cast)), this); Finder->addMatcher(binaryOperator(hasOperatorName("="), hasRHS(Cast)), this); Finder->addMatcher( binaryOperator(matchers::isComparisonOperator(), hasEitherOperand(Cast)), this); }
void NonCopyableObjectsCheck::registerMatchers(MatchFinder *Finder) { // There are two ways to get into trouble with objects like FILE *: // dereferencing the pointer type to be a non-pointer type, and declaring // the type as a non-pointer type in the first place. While the declaration // itself could technically be well-formed in the case where the type is not // an opaque type, it's highly suspicious behavior. // // POSIX types are a bit different in that it's reasonable to declare a // non-pointer variable or data member of the type, but it is not reasonable // to dereference a pointer to the type, or declare a parameter of non-pointer // type. auto BadFILEType = hasType(namedDecl(isFILEType()).bind("type_decl")); auto BadPOSIXType = hasType(namedDecl(isPOSIXType()).bind("type_decl")); auto BadEitherType = anyOf(BadFILEType, BadPOSIXType); Finder->addMatcher( namedDecl(anyOf(varDecl(BadFILEType), fieldDecl(BadFILEType))) .bind("decl"), this); Finder->addMatcher(parmVarDecl(BadPOSIXType).bind("decl"), this); Finder->addMatcher( expr(unaryOperator(hasOperatorName("*"), BadEitherType)).bind("expr"), this); }
StatementMatcher LoopMatcher = forStmt( // Node hasLoopInit( // Traversal declStmt( // Node hasSingleDecl( // Traversal varDecl( // Node hasInitializer( // Traversal integerLiteral( // Node equals( // Narrowing 0)))))))).bind("forLoop")
#include "ASTUtility.h" //match function here StatementMatcher callExprMatcher = callExpr(callee(functionDecl().bind("funcDecl"))).bind("callExpr"); //match var declarations here DeclarationMatcher varMatcher = varDecl().bind("var"); class StdPrinter : public MatchFinder::MatchCallback { public: virtual void run(const MatchFinder::MatchResult &Result) { //get the node clang::ASTContext *Context = Result.Context; const clang::CallExpr *call = Result.Nodes.getNodeAs<clang::CallExpr>("callExpr"); const clang::FunctionDecl *fun = Result.Nodes.getNodeAs<clang::FunctionDecl>("funcDecl"); const clang::VarDecl *var = Result.Nodes.getNodeAs<clang::VarDecl>("var"); if(call && !ASTUtility::IsStmtInSTDFile(call, Context)) { if (ASTUtility::IsDeclInSTDFile(fun, Context)) ASTUtility::Print(fun, Context, "Rule029.stmt.std"); else ASTUtility::Print(fun, Context, "Rule029.stmt.usr"); } if (var && !ASTUtility::IsDeclInSTDFile(var, Context)) { if (var -> getType().getAsString().find("std::") != std::string::npos) ASTUtility::Print(var, Context, "Rule029.decl.std"); else ASTUtility::Print(var, Context, "Rule029.decl.usr");
TEST(ParmVarDecl, KNRRange) { RangeVerifier<ParmVarDecl> Verifier; Verifier.expectRange(1, 8, 1, 8); EXPECT_TRUE(Verifier.match("void f(i) {}", varDecl(), Lang_C)); }
TEST(ParmVarDecl, KNRLocation) { LocationVerifier<ParmVarDecl> Verifier; Verifier.expectLocation(1, 8); EXPECT_TRUE(Verifier.match("void f(i) {}", varDecl(), Lang_C)); }
TEST(RangeVerifier, WrongRange) { RangeVerifier<VarDecl> Verifier; Verifier.expectRange(1, 1, 1, 1); EXPECT_FALSE(Verifier.match("int i;", varDecl())); }
TEST(LocationVerifier, WrongLocation) { LocationVerifier<VarDecl> Verifier; Verifier.expectLocation(1, 1); EXPECT_FALSE(Verifier.match("int i;", varDecl())); }
TEST(MatchVerifier, WrongType) { LocationVerifier<RecordDecl> Verifier; Verifier.expectLocation(1, 1); EXPECT_FALSE(Verifier.match("int i;", varDecl())); }