ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) { IdentifierInfo *first = sel.getIdentifierInfoForSlot(0); if (!first) return OMF_None; StringRef name = first->getName(); if (sel.isUnarySelector()) { if (name == "autorelease") return OMF_autorelease; if (name == "dealloc") return OMF_dealloc; if (name == "finalize") return OMF_finalize; if (name == "release") return OMF_release; if (name == "retain") return OMF_retain; if (name == "retainCount") return OMF_retainCount; if (name == "self") return OMF_self; if (name == "initialize") return OMF_initialize; } if (name == "performSelector") return OMF_performSelector; // The other method families may begin with a prefix of underscores. while (!name.empty() && name.front() == '_') name = name.substr(1); if (name.empty()) return OMF_None; switch (name.front()) { case 'a': if (startsWithWord(name, "alloc")) return OMF_alloc; break; case 'c': if (startsWithWord(name, "copy")) return OMF_copy; break; case 'i': if (startsWithWord(name, "init")) return OMF_init; break; case 'm': if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy; break; case 'n': if (startsWithWord(name, "new")) return OMF_new; break; default: break; } return OMF_None; }
bool CallGraph::includeInGraph(const Decl *D) { assert(D); if (!D->hasBody()) return false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // We skip function template definitions, as their semantics is // only determined when they are instantiated. if (FD->isDependentContext()) return false; IdentifierInfo *II = FD->getIdentifier(); if (II && II->getName().startswith("__inline")) return false; } return true; }
void WalkAST::VisitCallExpr(CallExpr *CE) { // Get the callee. const FunctionDecl *FD = CE->getDirectCallee(); if (!FD) return; // Get the name of the callee. If it's a builtin, strip off the prefix. IdentifierInfo *II = FD->getIdentifier(); if (!II) // if no identifier, not a simple C function return; StringRef Name = II->getName(); if (Name.startswith("__builtin_")) Name = Name.substr(10); // Set the evaluation function by switching on the callee name. FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) .Case("gets", &WalkAST::checkCall_gets) .Case("getpw", &WalkAST::checkCall_getpw) .Case("mktemp", &WalkAST::checkCall_mktemp) .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy) .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat) .Case("drand48", &WalkAST::checkCall_rand) .Case("erand48", &WalkAST::checkCall_rand) .Case("jrand48", &WalkAST::checkCall_rand) .Case("lrand48", &WalkAST::checkCall_rand) .Case("mrand48", &WalkAST::checkCall_rand) .Case("nrand48", &WalkAST::checkCall_rand) .Case("lcong48", &WalkAST::checkCall_rand) .Case("rand", &WalkAST::checkCall_rand) .Case("rand_r", &WalkAST::checkCall_rand) .Case("random", &WalkAST::checkCall_random) .Default(NULL); // If the callee isn't defined, it is not of security concern. // Check and evaluate the call. if (evalFunction) (this->*evalFunction)(CE, FD); // Recurse and check children. VisitChildren(CE); }
virtual Decl * ActOnDeclarator(Scope *S, Declarator &D) { std::cout << "------------------------------------------------\n"; // Print names of global variables. Differentiating between // global variables and global functions is Hard in C, so this // is only an approximation. const DeclSpec& DS = D.getDeclSpec(); SourceLocation loc = D.getIdentifierLoc(); if ( // Only global declarations... D.getContext() == Declarator::FileContext // ...that aren't typedefs or `extern` declarations... && DS.getStorageClassSpec() != DeclSpec::SCS_extern && DS.getStorageClassSpec() != DeclSpec::SCS_typedef // ...and no functions... && !D.isFunctionDeclarator() // ...and in a user header && !pp.getSourceManager().isInSystemHeader(loc) ) { IdentifierInfo *II = D.getIdentifier(); std::cout << "Found global user declarator " << II->getName().str() << std::endl; //raw_ostream& Out(); //Out << "Found global user declarator " << II->getName(); } else { //std::cout << ((D.getContext() == Declarator::FileContext) ? ("D.getContext() == Declarator::FileContext"):("D.getContext() != Declarator::FileContext")) << std::endl; //std::cout << ((DS.getStorageClassSpec() != DeclSpec::SCS_extern) ? ("DS.getStorageClassSpec() != DeclSpec::SCS_extern"):("DS.getStorageClassSpec() == DeclSpec::SCS_extern")) << std::endl; //std::cout << ((DS.getStorageClassSpec() != DeclSpec::SCS_typedef) ? ("DS.getStorageClassSpec() != DeclSpec::SCS_typedef"):("DS.getStorageClassSpec() == DeclSpec::SCS_typedef")) << std::endl; //std::cout << ((!D.isFunctionDeclarator()) ? ("!D.isFunctionDeclarator()"):("D.isFunctionDeclarator()")) << std::endl; //std::cout << ((!pp.getSourceManager().isInSystemHeader(loc)) ? ("!pp.getSourceManager().isInSystemHeader(loc)"):("pp.getSourceManager().isInSystemHeader(loc)")) << std::endl; } return Sema::ActOnDeclarator(S, D); }
bool is_of_class_for_MemberExpr(MemberExpr const * const e, std::string const & class_name) { ValueDecl const * decl = e->getMemberDecl(); QualType qt = decl->getType(); Type const * t = qt.getTypePtrOrNull(); if( t ) { RecordType const * rec = t->getAs<RecordType>(); if( rec ) { TagDecl const * tagdecl = rec->getDecl(); IdentifierInfo * idinfo = tagdecl->getIdentifier(); if( idinfo->getName() == class_name ) { return true; } } } return false; }
void PthreadLockChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { const ProgramState *state = C.getState(); const Expr *Callee = CE->getCallee(); const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); if (!FD) return; // Get the name of the callee. IdentifierInfo *II = FD->getIdentifier(); if (!II) // if no identifier, not a simple C function return; StringRef FName = II->getName(); if (CE->getNumArgs() != 1) return; if (FName == "pthread_mutex_lock" || FName == "pthread_rwlock_rdlock" || FName == "pthread_rwlock_wrlock") AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, PthreadSemantics); else if (FName == "lck_mtx_lock" || FName == "lck_rw_lock_exclusive" || FName == "lck_rw_lock_shared") AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, XNUSemantics); else if (FName == "pthread_mutex_trylock" || FName == "pthread_rwlock_tryrdlock" || FName == "pthread_rwlock_tryrwlock") AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, PthreadSemantics); else if (FName == "lck_mtx_try_lock" || FName == "lck_rw_try_lock_exclusive" || FName == "lck_rw_try_lock_shared") AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, XNUSemantics); else if (FName == "pthread_mutex_unlock" || FName == "pthread_rwlock_unlock" || FName == "lck_mtx_unlock" || FName == "lck_rw_done") ReleaseLock(C, CE, state->getSVal(CE->getArg(0))); }
/// \brief Handle \#pragma pop_macro. /// /// The syntax is: /// \code /// #pragma pop_macro("macro") /// \endcode void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) { SourceLocation MessageLoc = PopMacroTok.getLocation(); // Parse the pragma directive and get the macro IdentifierInfo*. IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PopMacroTok); if (!IdentInfo) return; // Find the vector<MacroInfo*> associated with the macro. llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> >::iterator iter = PragmaPushMacroInfo.find(IdentInfo); if (iter != PragmaPushMacroInfo.end()) { // Forget the MacroInfo currently associated with IdentInfo. if (MacroDirective *CurrentMD = getMacroDirective(IdentInfo)) { MacroInfo *MI = CurrentMD->getMacroInfo(); if (MI->isWarnIfUnused()) WarnUnusedMacroLocs.erase(MI->getDefinitionLoc()); appendMacroDirective(IdentInfo, AllocateUndefMacroDirective(MessageLoc)); } // Get the MacroInfo we want to reinstall. MacroInfo *MacroToReInstall = iter->second.back(); if (MacroToReInstall) { // Reinstall the previously pushed macro. appendDefMacroDirective(IdentInfo, MacroToReInstall, MessageLoc, /*isImported=*/false, /*Overrides*/None); } // Pop PragmaPushMacroInfo stack. iter->second.pop_back(); if (iter->second.size() == 0) PragmaPushMacroInfo.erase(iter); } else { Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push) << IdentInfo->getName(); } }
StringRef Selector::getNameForSlot(unsigned int argIndex) const { IdentifierInfo *II = getIdentifierInfoForSlot(argIndex); return II? II->getName() : StringRef(); }
static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const AttributeList &A, SourceRange) { IdentifierLoc *PragmaNameLoc = A.getArgAsIdent(0); IdentifierLoc *OptionLoc = A.getArgAsIdent(1); IdentifierLoc *StateLoc = A.getArgAsIdent(2); Expr *ValueExpr = A.getArgAsExpr(3); bool PragmaUnroll = PragmaNameLoc->Ident->getName() == "unroll"; bool PragmaNoUnroll = PragmaNameLoc->Ident->getName() == "nounroll"; if (St->getStmtClass() != Stmt::DoStmtClass && St->getStmtClass() != Stmt::ForStmtClass && St->getStmtClass() != Stmt::CXXForRangeStmtClass && St->getStmtClass() != Stmt::WhileStmtClass) { const char *Pragma = llvm::StringSwitch<const char *>(PragmaNameLoc->Ident->getName()) .Case("unroll", "#pragma unroll") .Case("nounroll", "#pragma nounroll") .Default("#pragma clang loop"); S.Diag(St->getLocStart(), diag::err_pragma_loop_precedes_nonloop) << Pragma; return nullptr; } LoopHintAttr::OptionType Option; LoopHintAttr::Spelling Spelling; if (PragmaUnroll) { Option = ValueExpr ? LoopHintAttr::UnrollCount : LoopHintAttr::Unroll; Spelling = LoopHintAttr::Pragma_unroll; } else if (PragmaNoUnroll) { Option = LoopHintAttr::Unroll; Spelling = LoopHintAttr::Pragma_nounroll; } else { assert(OptionLoc && OptionLoc->Ident && "Attribute must have valid option info."); IdentifierInfo *OptionInfo = OptionLoc->Ident; Option = llvm::StringSwitch<LoopHintAttr::OptionType>(OptionInfo->getName()) .Case("vectorize", LoopHintAttr::Vectorize) .Case("vectorize_width", LoopHintAttr::VectorizeWidth) .Case("interleave", LoopHintAttr::Interleave) .Case("interleave_count", LoopHintAttr::InterleaveCount) .Case("unroll", LoopHintAttr::Unroll) .Case("unroll_count", LoopHintAttr::UnrollCount) .Default(LoopHintAttr::Vectorize); Spelling = LoopHintAttr::Pragma_clang_loop; } LoopHintAttr::LoopHintState State = LoopHintAttr::Default; if (PragmaNoUnroll) { State = LoopHintAttr::Disable; } else if (Option == LoopHintAttr::VectorizeWidth || Option == LoopHintAttr::InterleaveCount || Option == LoopHintAttr::UnrollCount) { assert(ValueExpr && "Attribute must have a valid value expression."); if (S.CheckLoopHintExpr(ValueExpr, St->getLocStart())) return nullptr; } else if (Option == LoopHintAttr::Vectorize || Option == LoopHintAttr::Interleave || Option == LoopHintAttr::Unroll) { // Default state is assumed if StateLoc is not specified, such as with // '#pragma unroll'. if (StateLoc && StateLoc->Ident) { if (StateLoc->Ident->isStr("disable")) State = LoopHintAttr::Disable; else State = LoopHintAttr::Enable; } } return LoopHintAttr::CreateImplicit(S.Context, Spelling, Option, State, ValueExpr, A.getRange()); }
void TypePrinter::printTypeSpec(const NamedDecl *D, raw_ostream &OS) { IdentifierInfo *II = D->getIdentifier(); OS << II->getName(); spaceBeforePlaceHolder(OS); }
/// Parse an identifier in an MS-style inline assembly block. /// /// \param CastInfo - a void* so that we don't have to teach Parser.h /// about the actual type. ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, unsigned &NumLineToksConsumed, void *CastInfo, bool IsUnevaluatedContext) { llvm::InlineAsmIdentifierInfo &Info = *(llvm::InlineAsmIdentifierInfo *)CastInfo; // Push a fake token on the end so that we don't overrun the token // stream. We use ';' because it expression-parsing should never // overrun it. const tok::TokenKind EndOfStream = tok::semi; Token EndOfStreamTok; EndOfStreamTok.startToken(); EndOfStreamTok.setKind(EndOfStream); LineToks.push_back(EndOfStreamTok); // Also copy the current token over. LineToks.push_back(Tok); PP.EnterTokenStream(LineToks.begin(), LineToks.size(), /*disable macros*/ true, /*owns tokens*/ false); // Clear the current token and advance to the first token in LineToks. ConsumeAnyToken(); // Parse an optional scope-specifier if we're in C++. CXXScopeSpec SS; if (getLangOpts().CPlusPlus) { ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); } // Require an identifier here. SourceLocation TemplateKWLoc; UnqualifiedId Id; bool Invalid = true; ExprResult Result; if (Tok.is(tok::kw_this)) { Result = ParseCXXThis(); Invalid = false; } else { Invalid = ParseUnqualifiedId(SS, /*EnteringContext=*/false, /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, /*ObjectType=*/ParsedType(), TemplateKWLoc, Id); // Perform the lookup. Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, IsUnevaluatedContext); } // While the next two tokens are 'period' 'identifier', repeatedly parse it as // a field access. We have to avoid consuming assembler directives that look // like '.' 'else'. while (Result.isUsable() && Tok.is(tok::period)) { Token IdTok = PP.LookAhead(0); if (IdTok.isNot(tok::identifier)) break; ConsumeToken(); // Consume the period. IdentifierInfo *Id = Tok.getIdentifierInfo(); ConsumeToken(); // Consume the identifier. Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(), Info, Tok.getLocation()); } // Figure out how many tokens we are into LineToks. unsigned LineIndex = 0; if (Tok.is(EndOfStream)) { LineIndex = LineToks.size() - 2; } else { while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { LineIndex++; assert(LineIndex < LineToks.size() - 2); // we added two extra tokens } } // If we've run into the poison token we inserted before, or there // was a parsing error, then claim the entire line. if (Invalid || Tok.is(EndOfStream)) { NumLineToksConsumed = LineToks.size() - 2; } else { // Otherwise, claim up to the start of the next token. NumLineToksConsumed = LineIndex; } // Finally, restore the old parsing state by consuming all the tokens we // staged before, implicitly killing off the token-lexer we pushed. for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) { ConsumeAnyToken(); } assert(Tok.is(EndOfStream)); ConsumeToken(); // Leave LineToks in its original state. LineToks.pop_back(); LineToks.pop_back(); return Result; }
Optional<RetainSummaryManager::BehaviorSummary> RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD, bool &hasTrustedImplementationAnnotation) { IdentifierInfo *II = FD->getIdentifier(); if (!II) return None; StringRef FName = II->getName(); FName = FName.substr(FName.find_first_not_of('_')); QualType ResultTy = CE->getCallReturnType(Ctx); if (ResultTy->isObjCIdType()) { if (II->isStr("NSMakeCollectable")) return BehaviorSummary::Identity; } else if (ResultTy->isPointerType()) { // Handle: (CF|CG|CV)Retain // CFAutorelease // It's okay to be a little sloppy here. if (FName == "CMBufferQueueDequeueAndRetain" || FName == "CMBufferQueueDequeueIfDataReadyAndRetain") { // Part of: <rdar://problem/39390714>. // These are not retain. They just return something and retain it. return None; } if (CE->getNumArgs() == 1 && (cocoa::isRefType(ResultTy, "CF", FName) || cocoa::isRefType(ResultTy, "CG", FName) || cocoa::isRefType(ResultTy, "CV", FName)) && (isRetain(FD, FName) || isAutorelease(FD, FName) || isMakeCollectable(FName))) return BehaviorSummary::Identity; // safeMetaCast is called by OSDynamicCast. // We assume that OSDynamicCast is either an identity (cast is OK, // the input was non-zero), // or that it returns zero (when the cast failed, or the input // was zero). if (TrackOSObjects) { if (isOSObjectDynamicCast(FName) && FD->param_size() >= 1) { return BehaviorSummary::IdentityOrZero; } else if (isOSObjectThisCast(FName) && isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { return BehaviorSummary::IdentityThis; } } const FunctionDecl* FDD = FD->getDefinition(); if (FDD && isTrustedReferenceCountImplementation(FDD)) { hasTrustedImplementationAnnotation = true; return BehaviorSummary::Identity; } } if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { const CXXRecordDecl *Parent = MD->getParent(); if (TrackOSObjects && Parent && isOSObjectSubclass(Parent)) if (FName == "release" || FName == "retain") return BehaviorSummary::NoOp; } return None; }
/// \brief Handle the microsoft \#pragma comment extension. /// /// The syntax is: /// \code /// #pragma comment(linker, "foo") /// \endcode /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. /// "foo" is a string, which is fully macro expanded, and permits string /// concatenation, embedded escape characters etc. See MSDN for more details. void PragmaCommentHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) { SourceLocation CommentLoc = Tok.getLocation(); PP.Lex(Tok); if (Tok.isNot(tok::l_paren)) { PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); return; } // Read the identifier. PP.Lex(Tok); if (Tok.isNot(tok::identifier)) { PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); return; } // Verify that this is one of the 5 whitelisted options. IdentifierInfo *II = Tok.getIdentifierInfo(); Sema::PragmaMSCommentKind Kind = llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName()) .Case("linker", Sema::PCK_Linker) .Case("lib", Sema::PCK_Lib) .Case("compiler", Sema::PCK_Compiler) .Case("exestr", Sema::PCK_ExeStr) .Case("user", Sema::PCK_User) .Default(Sema::PCK_Unknown); if (Kind == Sema::PCK_Unknown) { PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); return; } // Read the optional string if present. PP.Lex(Tok); std::string ArgumentString; if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, "pragma comment", /*MacroExpansion=*/true)) return; // FIXME: warn that 'exestr' is deprecated. // FIXME: If the kind is "compiler" warn if the string is present (it is // ignored). // The MSDN docs say that "lib" and "linker" require a string and have a short // whitelist of linker options they support, but in practice MSVC doesn't // issue a diagnostic. Therefore neither does clang. if (Tok.isNot(tok::r_paren)) { PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); return; } PP.Lex(Tok); // eat the r_paren. if (Tok.isNot(tok::eod)) { PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); return; } // If the pragma is lexically sound, notify any interested PPCallbacks. if (PP.getPPCallbacks()) PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); Actions.ActOnPragmaMSComment(Kind, ArgumentString); }