// Do we know that we will eventually codegen the given function? static bool IsKnownEmitted(Sema &S, FunctionDecl *FD) { // Templates are emitted when they're instantiated. if (FD->isDependentContext()) return false; // When compiling for device, host functions are never emitted. Similarly, // when compiling for host, device and global functions are never emitted. // (Technically, we do emit a host-side stub for global functions, but this // doesn't count for our purposes here.) Sema::CUDAFunctionTarget T = S.IdentifyCUDATarget(FD); if (S.getLangOpts().CUDAIsDevice && T == Sema::CFT_Host) return false; if (!S.getLangOpts().CUDAIsDevice && (T == Sema::CFT_Device || T == Sema::CFT_Global)) return false; // Check whether this function is externally visible -- if so, it's // known-emitted. // // We have to check the GVA linkage of the function's *definition* -- if we // only have a declaration, we don't know whether or not the function will be // emitted, because (say) the definition could include "inline". FunctionDecl *Def = FD->getDefinition(); if (Def && !isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(Def))) return true; // Otherwise, the function is known-emitted if it's in our set of // known-emitted functions. return S.DeviceKnownEmittedFns.count(FD) > 0; }
bool VisitCompoundStmt(CompoundStmt* CS) { for(CompoundStmt::body_iterator I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { if (!isa<BinaryOperator>(*I)) continue; const BinaryOperator* BinOp = cast<BinaryOperator>(*I); if (isAutoCandidate(BinOp)) { ASTContext& C = m_Sema->getASTContext(); VarDecl* VD = cast<VarDecl>(cast<DeclRefExpr>(BinOp->getLHS())->getDecl()); TypeSourceInfo* ResTSI = 0; TypeSourceInfo* TrivialTSI = C.getTrivialTypeSourceInfo(VD->getType()); Expr* RHS = BinOp->getRHS(); m_Sema->DeduceAutoType(TrivialTSI, RHS, ResTSI); VD->setTypeSourceInfo(ResTSI); VD->setType(ResTSI->getType()); VD->setInit(RHS); Sema::DeclGroupPtrTy VDPtrTy = m_Sema->ConvertDeclToDeclGroup(VD); // Transform the AST into a "sane" state. Replace the binary operator // with decl stmt, because the binop semantically is a decl with init. StmtResult DS = m_Sema->ActOnDeclStmt(VDPtrTy, BinOp->getLocStart(), BinOp->getLocEnd()); assert(!DS.isInvalid() && "Invalid DeclStmt."); *I = DS.take(); } } return true; // returning false will abort the in-depth traversal. }
~InterpreterExternalSemaSource() { // FIXME: Another gross hack due to the missing multiplexing AST external // source see Interpreter::setCallbacks. if (m_Sema) { ASTContext& C = m_Sema->getASTContext(); // tell the owning ptr to not delete it, the callbacks will delete it. if (C.ExternalSource.get() == this) C.ExternalSource.resetWithoutRelease(); } }
static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) { // Don't issue a fixit if there is already an initializer. if (VD->getInit()) return; // Suggest possible initialization (if any). const char *initialization = 0; QualType VariableTy = VD->getType().getCanonicalType(); if (VariableTy->isObjCObjectPointerType() || VariableTy->isBlockPointerType()) { // Check if 'nil' is defined. if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) initialization = " = nil"; else initialization = " = 0"; } else if (VariableTy->isRealFloatingType()) initialization = " = 0.0"; else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) initialization = " = false"; else if (VariableTy->isEnumeralType()) return; else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) { // Check if 'NULL' is defined. if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL"))) initialization = " = NULL"; else initialization = " = 0"; } else if (VariableTy->isScalarType()) initialization = " = 0"; if (initialization) { SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); S.Diag(loc, diag::note_var_fixit_add_initialization) << FixItHint::CreateInsertion(loc, initialization); } }
void Fix(CompoundStmt* CS) { if (!CS->size()) return; typedef llvm::SmallVector<Stmt*, 32> Statements; Statements Stmts; Stmts.append(CS->body_begin(), CS->body_end()); for (Statements::iterator I = Stmts.begin(); I != Stmts.end(); ++I) { if (!TraverseStmt(*I) && !m_HandledDecls.count(m_FoundDRE->getDecl())) { Sema::DeclGroupPtrTy VDPtrTy = m_Sema->ConvertDeclToDeclGroup(m_FoundDRE->getDecl()); StmtResult DS = m_Sema->ActOnDeclStmt(VDPtrTy, m_FoundDRE->getLocStart(), m_FoundDRE->getLocEnd()); assert(!DS.isInvalid() && "Invalid DeclStmt."); I = Stmts.insert(I, DS.take()); m_HandledDecls.insert(m_FoundDRE->getDecl()); } } CS->setStmts(m_Sema->getASTContext(), Stmts.data(), Stmts.size()); }
void IncrementalParser::Initialize() { if (hasCodeGenerator()) getCodeGenerator()->Initialize(getCI()->getASTContext()); CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = CompilationOptions::VPDisabled; CO.CodeGeneration = hasCodeGenerator(); // pull in PCHs const std::string& PCHFileName = m_CI->getInvocation ().getPreprocessorOpts().ImplicitPCHInclude; if (!PCHFileName.empty()) { Transaction* CurT = beginTransaction(CO); m_CI->createPCHExternalASTSource(PCHFileName, true /*DisablePCHValidation*/, true /*AllowPCHWithCompilerErrors*/, 0 /*DeserializationListener*/); Transaction* EndedT = endTransaction(CurT); commitTransaction(EndedT); } Transaction* CurT = beginTransaction(CO); Sema* TheSema = &m_CI->getSema(); m_Parser.reset(new Parser(m_CI->getPreprocessor(), *TheSema, false /*skipFuncBodies*/)); m_CI->getPreprocessor().EnterMainSourceFile(); // Initialize the parser after we have entered the main source file. m_Parser->Initialize(); // Perform initialization that occurs after the parser has been initialized // but before it parses anything. Initializes the consumers too. TheSema->Initialize(); ExternalASTSource *External = TheSema->getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(m_Consumer); Transaction* EndedT = endTransaction(CurT); commitTransaction(EndedT); }
// Do we know that we will eventually codegen the given function? static bool IsKnownEmitted(Sema &S, FunctionDecl *FD) { // Templates are emitted when they're instantiated. if (FD->isDependentContext()) return false; // When compiling for device, host functions are never emitted. Similarly, // when compiling for host, device and global functions are never emitted. // (Technically, we do emit a host-side stub for global functions, but this // doesn't count for our purposes here.) Sema::CUDAFunctionTarget T = S.IdentifyCUDATarget(FD); if (S.getLangOpts().CUDAIsDevice && T == Sema::CFT_Host) return false; if (!S.getLangOpts().CUDAIsDevice && (T == Sema::CFT_Device || T == Sema::CFT_Global)) return false; // Externally-visible and similar functions are always emitted. if (!isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(FD))) return true; // Otherwise, the function is known-emitted if it's in our set of // known-emitted functions. return S.CUDAKnownEmittedFns.count(FD) > 0; }
PointerCheckInjector(Sema& S) : m_Sema(S), m_Context(S.getASTContext()), m_clingthrowIfInvalidPointerCache(0) {}
// Deal with all the call expr in the transaction. bool VisitCallExpr(CallExpr* TheCall) { if (FunctionDecl* FDecl = TheCall->getDirectCallee()) { std::bitset<32> ArgIndexs; for (FunctionDecl::redecl_iterator RI = FDecl->redecls_begin(), RE = FDecl->redecls_end(); RI != RE; ++RI) { for (specific_attr_iterator<NonNullAttr> I = RI->specific_attr_begin<NonNullAttr>(), E = RI->specific_attr_end<NonNullAttr>(); I != E; ++I) { NonNullAttr *NonNull = *I; // Store all the null attr argument's index into "ArgIndexs". for (NonNullAttr::args_iterator i = NonNull->args_begin(), e = NonNull->args_end(); i != e; ++i) { // Get the argument with the nonnull attribute. const Expr* Arg = TheCall->getArg(*i); // Check whether we can get the argument'value. If the argument is // not null, then ignore this argument and continue to deal with the // next argument with the nonnull attribute.ArgIndexs.set(*i); bool Result; ASTContext& Context = m_Sema->getASTContext(); if (Arg->EvaluateAsBooleanCondition(Result, Context) && Result) { continue; } ArgIndexs.set(*i); } break; } } if (ArgIndexs.any()) { // Get the function decl's name. std::string FName = getMangledName(FDecl); // Store the function decl's name into the vector. m_NonNullDeclNames.push_back(FName); // Store the function decl's name with its null attr args' indexes // into the map. m_NonNullArgIndexs.insert(std::make_pair(FName, ArgIndexs)); } // FIXME: For now we will only work/check on declarations that are not // deserialized. We want to avoid our null deref transaformer to // deserialize all the contents of a PCH/PCM. // We have to think of a better way to find the annotated // declarations, without that to cause too much deserialization. Stmt* S = (FDecl->isFromASTFile()) ? 0 : FDecl->getBody(); if (S) { for (Stmt::child_iterator II = S->child_begin(), EE = S->child_end(); II != EE; ++II) { CallExpr* child = dyn_cast<CallExpr>(*II); if (child && child->getDirectCallee() != FDecl) VisitCallExpr(child); } } } return true; // returning false will abort the in-depth traversal. }
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::EnableStatistics(); Stmt::EnableStatistics(); } // Also turn on collection of stats inside of the Sema object. bool OldCollectStats = PrintStats; std::swap(OldCollectStats, S.CollectStats); ASTConsumer *Consumer = &S.getASTConsumer(); OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); PrettyStackTraceParserEntry CrashInfo(P); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Parser> CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); S.Initialize(); // C11 6.9p1 says translation units must have at least one top-level // declaration. C++ doesn't have this restriction. We also don't want to // complain if we have a precompiled header, although technically if the PCH // is empty we should still emit the (pedantic) diagnostic. Parser::DeclGroupPtrTy ADecl; ExternalASTSource *External = S.getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(Consumer); if (P.ParseTopLevelDecl(ADecl)) { if (!External && !S.getLangOpts().CPlusPlus) P.Diag(diag::ext_empty_translation_unit); } else { do { // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) return; } while (!P.ParseTopLevelDecl(ADecl)); } // Process any TopLevelDecls generated by #pragma weak. for (SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(), E = S.WeakTopLevelDecls().end(); I != E; ++I) Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); Consumer->HandleTranslationUnit(S.getASTContext()); std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; P.getActions().PrintStats(); S.getASTContext().PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); Consumer->PrintStats(); } }
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::EnableStatistics(); Stmt::EnableStatistics(); } // Also turn on collection of stats inside of the Sema object. bool OldCollectStats = PrintStats; std::swap(OldCollectStats, S.CollectStats); // Initialize the template instantiation observer chain. // FIXME: See note on "finalize" below. initialize(S.TemplateInstCallbacks, S); ASTConsumer *Consumer = &S.getASTConsumer(); std::unique_ptr<Parser> ParseOP( new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> CleanupPrettyStack(llvm::SavePrettyStackState()); PrettyStackTraceParserEntry CrashInfo(P); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<Parser> CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); P.Initialize(); Parser::DeclGroupPtrTy ADecl; ExternalASTSource *External = S.getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(Consumer); for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; AtEOF = P.ParseTopLevelDecl(ADecl)) { // If we got a null return and something *was* parsed, ignore it. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) return; } // Process any TopLevelDecls generated by #pragma weak. for (Decl *D : S.WeakTopLevelDecls()) Consumer->HandleTopLevelDecl(DeclGroupRef(D)); Consumer->HandleTranslationUnit(S.getASTContext()); // Finalize the template instantiation observer chain. // FIXME: This (and init.) should be done in the Sema class, but because // Sema does not have a reliable "Finalize" function (it has a // destructor, but it is not guaranteed to be called ("-disable-free")). // So, do the initialization above and do the finalization here: finalize(S.TemplateInstCallbacks, S); std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; P.getActions().PrintStats(); S.getASTContext().PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); Consumer->PrintStats(); } }
bool IncrementalParser::Initialize(llvm::SmallVectorImpl<ParseResultTransaction>& result, bool isChildInterpreter) { m_TransactionPool.reset(new TransactionPool); if (hasCodeGenerator()) getCodeGenerator()->Initialize(getCI()->getASTContext()); CompilationOptions CO = m_Interpreter->makeDefaultCompilationOpts(); Transaction* CurT = beginTransaction(CO); Preprocessor& PP = m_CI->getPreprocessor(); DiagnosticsEngine& Diags = m_CI->getSema().getDiagnostics(); // Pull in PCH. const std::string& PCHFileName = m_CI->getInvocation().getPreprocessorOpts().ImplicitPCHInclude; if (!PCHFileName.empty()) { Transaction* PchT = beginTransaction(CO); DiagnosticErrorTrap Trap(Diags); m_CI->createPCHExternalASTSource(PCHFileName, true /*DisablePCHValidation*/, true /*AllowPCHWithCompilerErrors*/, 0 /*DeserializationListener*/, true /*OwnsDeserializationListener*/); result.push_back(endTransaction(PchT)); if (Trap.hasErrorOccurred()) { result.push_back(endTransaction(CurT)); return false; } } addClingPragmas(*m_Interpreter); // Must happen after attaching the PCH, else PCH elements will end up // being lexed. PP.EnterMainSourceFile(); Sema* TheSema = &m_CI->getSema(); m_Parser.reset(new Parser(PP, *TheSema, false /*skipFuncBodies*/)); // Initialize the parser after PP has entered the main source file. m_Parser->Initialize(); ExternalASTSource *External = TheSema->getASTContext().getExternalSource(); if (External) External->StartTranslationUnit(m_Consumer); // Start parsing the "main file" to warm up lexing (enter caching lex mode // for ParseInternal()'s call EnterSourceFile() to make sense. while (!m_Parser->ParseTopLevelDecl()) {} // If I belong to the parent Interpreter, am using C++, and -noruntime // wasn't given on command line, then #include <new> and check ABI if (!isChildInterpreter && m_CI->getLangOpts().CPlusPlus && !m_Interpreter->getOptions().NoRuntime) { // <new> is needed by the ValuePrinter so it's a good thing to include it. // We need to include it to determine the version number of the standard // library implementation. ParseInternal("#include <new>"); // That's really C++ ABI compatibility. C has other problems ;-) CheckABICompatibility(*m_Interpreter); } // DO NOT commit the transactions here: static initialization in these // transactions requires gCling through local_cxa_atexit(), but that has not // been defined yet! ParseResultTransaction PRT = endTransaction(CurT); result.push_back(PRT); return true; }