diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTConsumers.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/ASTMerge.cpp | 103 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 30 | ||||
-rw-r--r-- | lib/Frontend/AnalysisConsumer.cpp | 161 | ||||
-rw-r--r-- | lib/Frontend/Backend.cpp | 38 | ||||
-rw-r--r-- | lib/Frontend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 54 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 41 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/HTMLDiagnostics.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 10 | ||||
-rw-r--r-- | lib/Frontend/InitPreprocessor.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/Makefile | 1 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 44 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 13 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderStmt.cpp | 33 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 35 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterStmt.cpp | 21 | ||||
-rw-r--r-- | lib/Frontend/PlistDiagnostics.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/PrintParserCallbacks.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/RewriteObjC.cpp | 448 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticPrinter.cpp | 26 |
23 files changed, 718 insertions, 360 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 33cb94e..ebbd720 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -564,7 +564,7 @@ public: if (RD->isInvalidDecl()) continue; - if (!RD->getDefinition(C)) + if (!RD->getDefinition()) continue; // FIXME: Do we really need to hard code this? diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp new file mode 100644 index 0000000..2228ea4 --- /dev/null +++ b/lib/Frontend/ASTMerge.cpp @@ -0,0 +1,103 @@ +//===-- ASTMerge.cpp - AST Merging Frontent Action --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTImporter.h" + +using namespace clang; + +ASTConsumer *ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) { + return AdaptedAction->CreateASTConsumer(CI, InFile); +} + +bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename) { + // FIXME: This is a hack. We need a better way to communicate the + // AST file, compiler instance, and file name than member variables + // of FrontendAction. + AdaptedAction->setCurrentFile(getCurrentFile(), takeCurrentASTUnit()); + AdaptedAction->setCompilerInstance(&CI); + return AdaptedAction->BeginSourceFileAction(CI, Filename); +} + +void ASTMergeAction::ExecuteAction() { + CompilerInstance &CI = getCompilerInstance(); + CI.getDiagnostics().getClient()->BeginSourceFile( + CI.getASTContext().getLangOptions()); + CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, + &CI.getASTContext()); + for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { + ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], CI.getDiagnostics(), + false); + if (!Unit) + continue; + + ASTImporter Importer(CI.getDiagnostics(), + CI.getASTContext(), + CI.getFileManager(), + Unit->getASTContext(), + Unit->getFileManager()); + + TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); + for (DeclContext::decl_iterator D = TU->decls_begin(), + DEnd = TU->decls_end(); + D != DEnd; ++D) { + // Don't re-import __va_list_tag, __builtin_va_list. + if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) + if (IdentifierInfo *II = ND->getIdentifier()) + if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) + continue; + + Importer.Import(*D); + } + + delete Unit; + } + + AdaptedAction->ExecuteAction(); + CI.getDiagnostics().getClient()->EndSourceFile(); +} + +void ASTMergeAction::EndSourceFileAction() { + return AdaptedAction->EndSourceFileAction(); +} + +ASTMergeAction::ASTMergeAction(FrontendAction *AdaptedAction, + std::string *ASTFiles, unsigned NumASTFiles) + : AdaptedAction(AdaptedAction), ASTFiles(ASTFiles, ASTFiles + NumASTFiles) { + assert(AdaptedAction && "ASTMergeAction needs an action to adapt"); +} + +ASTMergeAction::~ASTMergeAction() { + delete AdaptedAction; +} + +bool ASTMergeAction::usesPreprocessorOnly() const { + return AdaptedAction->usesPreprocessorOnly(); +} + +bool ASTMergeAction::usesCompleteTranslationUnit() { + return AdaptedAction->usesCompleteTranslationUnit(); +} + +bool ASTMergeAction::hasPCHSupport() const { + return AdaptedAction->hasPCHSupport(); +} + +bool ASTMergeAction::hasASTSupport() const { + return AdaptedAction->hasASTSupport(); +} + +bool ASTMergeAction::hasCodeCompletionSupport() const { + return AdaptedAction->hasCodeCompletionSupport(); +} diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 2fb47cb..a0c4889 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -98,13 +98,12 @@ const std::string &ASTUnit::getOriginalSourceFileName() { const std::string &ASTUnit::getPCHFileName() { assert(isMainFileAST() && "Not an ASTUnit from a PCH file!"); - return dyn_cast<PCHReader>(Ctx->getExternalSource())->getFileName(); + return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName(); } ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, Diagnostic &Diags, bool OnlyLocalDecls, - bool UseBumpAllocator, RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true)); @@ -184,7 +183,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, PP.getIdentifierTable(), PP.getSelectorTable(), PP.getBuiltinInfo(), - /* FreeMemory = */ !UseBumpAllocator, + /* FreeMemory = */ false, /* size_reserve = */0)); ASTContext &Context = *AST->Ctx.get(); @@ -230,7 +229,7 @@ public: } -ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI, +ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, Diagnostic &Diags, bool OnlyLocalDecls) { // Create the compiler instance to use for building the AST. @@ -238,7 +237,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI, llvm::OwningPtr<ASTUnit> AST; llvm::OwningPtr<TopLevelDeclTrackerAction> Act; - Clang.getInvocation() = CI; + Clang.setInvocation(CI); Clang.setDiagnostics(&Diags); Clang.setDiagnosticClient(Diags.getClient()); @@ -294,7 +293,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI, Clang.takeDiagnosticClient(); Clang.takeDiagnostics(); + Clang.takeInvocation(); + AST->Invocation.reset(Clang.takeInvocation()); return AST.take(); error: @@ -310,7 +311,6 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, Diagnostic &Diags, llvm::StringRef ResourceFilesPath, bool OnlyLocalDecls, - bool UseBumpAllocator, RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { llvm::SmallVector<const char *, 16> Args; @@ -324,6 +324,10 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, // FIXME: We shouldn't have to pass in the path info. driver::Driver TheDriver("clang", "/", llvm::sys::getHostTriple(), "a.out", false, Diags); + + // Don't check that inputs exist, they have been remapped. + TheDriver.setCheckInputsExist(false); + llvm::OwningPtr<driver::Compilation> C( TheDriver.BuildCompilation(Args.size(), Args.data())); @@ -345,19 +349,19 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, } const driver::ArgStringList &CCArgs = Cmd->getArguments(); - CompilerInvocation CI; - CompilerInvocation::CreateFromArgs(CI, (const char**) CCArgs.data(), + llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation); + CompilerInvocation::CreateFromArgs(*CI, (const char**) CCArgs.data(), (const char**) CCArgs.data()+CCArgs.size(), Diags); // Override any files that need remapping for (unsigned I = 0; I != NumRemappedFiles; ++I) - CI.getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, - RemappedFiles[I].second); + CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, + RemappedFiles[I].second); // Override the resources path. - CI.getHeaderSearchOpts().ResourceDir = ResourceFilesPath; + CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; - CI.getFrontendOpts().DisableFree = UseBumpAllocator; - return LoadFromCompilerInvocation(CI, Diags, OnlyLocalDecls); + CI->getFrontendOpts().DisableFree = true; + return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls); } diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index 45a3b15..d764fd0 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -18,14 +18,15 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ParentMap.h" #include "clang/Analysis/Analyses/LiveVariables.h" +#include "clang/Analysis/Analyses/UninitializedValues.h" #include "clang/Analysis/CFG.h" -#include "clang/Analysis/LocalCheckers.h" -#include "clang/Analysis/ManagerRegistry.h" -#include "clang/Analysis/PathDiagnostic.h" -#include "clang/Analysis/PathSensitive/AnalysisManager.h" -#include "clang/Analysis/PathSensitive/BugReporter.h" -#include "clang/Analysis/PathSensitive/GRExprEngine.h" -#include "clang/Analysis/PathSensitive/GRTransferFuncs.h" +#include "clang/Checker/Checkers/LocalCheckers.h" +#include "clang/Checker/ManagerRegistry.h" +#include "clang/Checker/BugReporter/PathDiagnostic.h" +#include "clang/Checker/PathSensitive/AnalysisManager.h" +#include "clang/Checker/BugReporter/BugReporter.h" +#include "clang/Checker/PathSensitive/GRExprEngine.h" +#include "clang/Checker/PathSensitive/GRTransferFuncs.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/PathDiagnosticClients.h" @@ -64,13 +65,17 @@ namespace { class AnalysisConsumer : public ASTConsumer { public: typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D); - + typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M, + TranslationUnitDecl &TU); + private: typedef std::vector<CodeAction> Actions; + typedef std::vector<TUAction> TUActions; + Actions FunctionActions; Actions ObjCMethodActions; Actions ObjCImplementationActions; - Actions TranslationUnitActions; + TUActions TranslationUnitActions; public: ASTContext* Ctx; @@ -133,11 +138,11 @@ public: } } } - + void DisplayFunction(const Decl *D) { if (!Opts.AnalyzerDisplayProgress || declDisplayed) return; - + declDisplayed = true; SourceManager &SM = Mgr->getASTContext().getSourceManager(); PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); @@ -162,7 +167,7 @@ public: ObjCImplementationActions.push_back(action); } - void addTranslationUnitAction(CodeAction action) { + void addTranslationUnitAction(TUAction action) { TranslationUnitActions.push_back(action); } @@ -191,7 +196,7 @@ public: namespace llvm { template <> struct FoldingSetTrait<AnalysisConsumer::CodeAction> { - static inline void Profile(AnalysisConsumer::CodeAction X, + static inline void Profile(AnalysisConsumer::CodeAction X, FoldingSetNodeID& ID) { ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X))); } @@ -204,42 +209,30 @@ namespace llvm { void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { switch (D->getKind()) { + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + case Decl::CXXMethod: case Decl::Function: { FunctionDecl* FD = cast<FunctionDecl>(D); - if (!Opts.AnalyzeSpecificFunction.empty() && - Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName()) - break; + FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction) + break; - Stmt* Body = FD->getBody(); - if (Body) HandleCode(FD, Body, FunctionActions); + if (Stmt *Body = FD->getBody()) + HandleCode(FD, Body, FunctionActions); break; } case Decl::ObjCMethod: { ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); - if (Opts.AnalyzeSpecificFunction.size() > 0 && + if (!Opts.AnalyzeSpecificFunction.empty() && Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString()) return; - Stmt* Body = MD->getBody(); - if (Body) HandleCode(MD, Body, ObjCMethodActions); - break; - } - - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - case Decl::CXXMethod: { - CXXMethodDecl *CXXMD = cast<CXXMethodDecl>(D); - - if (Opts.AnalyzeSpecificFunction.size() > 0 && - Opts.AnalyzeSpecificFunction != CXXMD->getName()) - return; - - Stmt *Body = CXXMD->getBody(); - if (Body) HandleCode(CXXMD, Body, FunctionActions); + if (Stmt* Body = MD->getBody()) + HandleCode(MD, Body, ObjCMethodActions); break; } @@ -249,30 +242,12 @@ void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { } void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { - + TranslationUnitDecl *TU = C.getTranslationUnitDecl(); - - if (!TranslationUnitActions.empty()) { - // Find the entry function definition (if any). - FunctionDecl *FD = 0; - // Must specify an entry function. - if (!Opts.AnalyzeSpecificFunction.empty()) { - for (DeclContext::decl_iterator I=TU->decls_begin(), E=TU->decls_end(); - I != E; ++I) { - if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I)) - if (fd->isThisDeclarationADefinition() && - fd->getNameAsString() == Opts.AnalyzeSpecificFunction) { - FD = fd; - break; - } - } - } - if (FD) { - for (Actions::iterator I = TranslationUnitActions.begin(), - E = TranslationUnitActions.end(); I != E; ++I) - (*I)(*this, *Mgr, FD); - } + for (TUActions::iterator I = TranslationUnitActions.begin(), + E = TranslationUnitActions.end(); I != E; ++I) { + (*I)(*this, *Mgr, *TU); } if (!ObjCImplementationActions.empty()) { @@ -293,7 +268,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) { if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) WL.push_back(BD); - + for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); I!=E; ++I) if (DeclContext *DC = dyn_cast<DeclContext>(*I)) @@ -314,14 +289,14 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) { // Clear the AnalysisManager of old AnalysisContexts. Mgr->ClearContexts(); - + // Dispatch on the actions. llvm::SmallVector<Decl*, 10> WL; WL.push_back(D); - + if (Body && Opts.AnalyzeNestedBlocks) FindBlocks(cast<DeclContext>(D), WL); - + for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I) for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end(); WI != WE; ++WI) @@ -351,7 +326,7 @@ static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr, static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, - Decl *D, + Decl *D, GRTransferFuncs* tf) { llvm::OwningPtr<GRTransferFuncs> TF(tf); @@ -363,18 +338,18 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, // information to see if the CFG is valid. // FIXME: Inter-procedural analysis will need to handle invalid CFGs. if (!mgr.getLiveVariables(D)) - return; - + return; + GRExprEngine Eng(mgr, TF.take()); - + if (C.Opts.EnableExperimentalInternalChecks) RegisterExperimentalInternalChecks(Eng); - + RegisterAppleChecks(Eng, *D); - + if (C.Opts.EnableExperimentalChecks) RegisterExperimentalChecks(Eng); - + // Set the graph auditor. llvm::OwningPtr<ExplodedNode::Auditor> Auditor; if (mgr.shouldVisualizeUbigraph()) { @@ -397,7 +372,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Eng.getBugReporter().FlushReports(); } -static void ActionCheckerCFRefAux(AnalysisConsumer &C, AnalysisManager& mgr, +static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D, bool GCEnabled) { GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(), @@ -407,23 +382,23 @@ static void ActionCheckerCFRefAux(AnalysisConsumer &C, AnalysisManager& mgr, ActionGRExprEngine(C, mgr, D, TF); } -static void ActionCheckerCFRef(AnalysisConsumer &C, AnalysisManager& mgr, +static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { switch (mgr.getLangOptions().getGCMode()) { default: assert (false && "Invalid GC mode."); case LangOptions::NonGC: - ActionCheckerCFRefAux(C, mgr, D, false); + ActionObjCMemCheckerAux(C, mgr, D, false); break; case LangOptions::GCOnly: - ActionCheckerCFRefAux(C, mgr, D, true); + ActionObjCMemCheckerAux(C, mgr, D, true); break; case LangOptions::HybridGC: - ActionCheckerCFRefAux(C, mgr, D, false); - ActionCheckerCFRefAux(C, mgr, D, true); + ActionObjCMemCheckerAux(C, mgr, D, false); + ActionObjCMemCheckerAux(C, mgr, D, true); break; } } @@ -457,6 +432,13 @@ static void ActionSecuritySyntacticChecks(AnalysisConsumer &C, CheckSecuritySyntaxOnly(D, BR); } +static void ActionLLVMConventionChecker(AnalysisConsumer &C, + AnalysisManager &mgr, + TranslationUnitDecl &TU) { + BugReporter BR(mgr); + CheckLLVMConventions(TU, BR); +} + static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) { if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly) @@ -489,8 +471,29 @@ static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr, } static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr, - Decl *D) { - // FIXME: This is largely copy of ActionGRExprEngine. Needs cleanup. + TranslationUnitDecl &TU) { + + // Find the entry function definition (if any). + FunctionDecl *D = 0; + + // Must specify an entry function. + if (!C.Opts.AnalyzeSpecificFunction.empty()) { + for (DeclContext::decl_iterator I=TU.decls_begin(), E=TU.decls_end(); + I != E; ++I) { + if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I)) + if (fd->isThisDeclarationADefinition() && + fd->getNameAsString() == C.Opts.AnalyzeSpecificFunction) { + D = fd; + break; + } + } + } + + if (!D) + return; + + + // FIXME: This is largely copy of ActionGRExprEngine. Needs cleanup. // Display progress. C.DisplayFunction(D); @@ -500,9 +503,9 @@ static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr, if (C.Opts.EnableExperimentalInternalChecks) RegisterExperimentalInternalChecks(Eng); - + RegisterAppleChecks(Eng, *D); - + if (C.Opts.EnableExperimentalChecks) RegisterExperimentalChecks(Eng); diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp index 9be6786..f5291a9 100644 --- a/lib/Frontend/Backend.cpp +++ b/lib/Frontend/Backend.cpp @@ -17,7 +17,6 @@ #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/Module.h" -#include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Assembly/PrintModulePass.h" @@ -56,7 +55,6 @@ namespace { llvm::Module *TheModule; llvm::TargetData *TheTargetData; - mutable llvm::ModuleProvider *ModuleProvider; mutable FunctionPassManager *CodeGenPasses; mutable PassManager *PerModulePasses; mutable FunctionPassManager *PerFunctionPasses; @@ -89,7 +87,7 @@ namespace { LLVMIRGeneration("LLVM IR Generation Time"), CodeGenerationTime("Code Generation Time"), Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)), - TheModule(0), TheTargetData(0), ModuleProvider(0), + TheModule(0), TheTargetData(0), CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) { if (AsmOutStream) @@ -101,7 +99,7 @@ namespace { ~BackendConsumer() { delete TheTargetData; - delete ModuleProvider; + delete TheModule; delete CodeGenPasses; delete PerModulePasses; delete PerFunctionPasses; @@ -116,7 +114,6 @@ namespace { Gen->Initialize(Ctx); TheModule = Gen->GetModule(); - ModuleProvider = new ExistingModuleProvider(TheModule); TheTargetData = new llvm::TargetData(Ctx.Target.getTargetDescription()); if (llvm::TimePassesIsEnabled) @@ -172,7 +169,7 @@ namespace { FunctionPassManager *BackendConsumer::getCodeGenPasses() const { if (!CodeGenPasses) { - CodeGenPasses = new FunctionPassManager(ModuleProvider); + CodeGenPasses = new FunctionPassManager(TheModule); CodeGenPasses->add(new TargetData(*TheTargetData)); } @@ -190,7 +187,7 @@ PassManager *BackendConsumer::getPerModulePasses() const { FunctionPassManager *BackendConsumer::getPerFunctionPasses() const { if (!PerFunctionPasses) { - PerFunctionPasses = new FunctionPassManager(ModuleProvider); + PerFunctionPasses = new FunctionPassManager(TheModule); PerFunctionPasses->add(new TargetData(*TheTargetData)); } @@ -306,20 +303,12 @@ bool BackendConsumer::AddEmitPasses() { case 3: OptLevel = CodeGenOpt::Aggressive; break; } - // Normal mode, emit a .s file by running the code generator. - // Note, this also adds codegenerator level optimization passes. - switch (TM->addPassesToEmitFile(*PM, FormattedOutStream, - TargetMachine::AssemblyFile, OptLevel)) { - default: - case FileModel::Error: - Diags.Report(diag::err_fe_unable_to_interface_with_target); - return false; - case FileModel::AsmFile: - break; - } - - if (TM->addPassesToEmitFileFinish(*CodeGenPasses, (MachineCodeEmitter *)0, - OptLevel)) { + // Normal mode, emit a .s or .o file by running the code generator. Note, + // this also adds codegenerator level optimization passes. + TargetMachine::CodeGenFileType CGFT = TargetMachine::CGFT_AssemblyFile; + if (Action == Backend_EmitObj) + CGFT = TargetMachine::CGFT_ObjectFile; + if (TM->addPassesToEmitFile(*PM, FormattedOutStream, CGFT, OptLevel)) { Diags.Report(diag::err_fe_unable_to_interface_with_target); return false; } @@ -354,11 +343,11 @@ void BackendConsumer::CreatePasses() { // Set the inline threshold following llvm-gcc. // // FIXME: Derive these constants in a principled fashion. - unsigned Threshold = 200; + unsigned Threshold = 225; if (CodeGenOpts.OptimizeSize) - Threshold = 50; + Threshold = 75; else if (OptLevel > 2) - Threshold = 250; + Threshold = 275; InliningPass = createFunctionInliningPass(Threshold); break; } @@ -392,7 +381,6 @@ void BackendConsumer::EmitAssembly() { if (!M) { // The module has been released by IR gen on failures, do not // double free. - ModuleProvider->releaseModule(); TheModule = 0; return; } diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 58aaa43..1d0b5c1 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_NO_RTTI 1) add_clang_library(clangFrontend ASTConsumers.cpp + ASTMerge.cpp ASTUnit.cpp AnalysisConsumer.cpp Backend.cpp diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 19c740d..917cbd7 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -35,15 +35,19 @@ #include "llvm/System/Program.h" using namespace clang; -CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext, - bool _OwnsLLVMContext) - : LLVMContext(_LLVMContext), - OwnsLLVMContext(_OwnsLLVMContext) { - } +CompilerInstance::CompilerInstance() + : Invocation(new CompilerInvocation()) { +} CompilerInstance::~CompilerInstance() { - if (OwnsLLVMContext) - delete LLVMContext; +} + +void CompilerInstance::setLLVMContext(llvm::LLVMContext *Value) { + LLVMContext.reset(Value); +} + +void CompilerInstance::setInvocation(CompilerInvocation *Value) { + Invocation.reset(Value); } void CompilerInstance::setDiagnostics(Diagnostic *Value) { @@ -83,6 +87,23 @@ void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) { } // Diagnostics +namespace { + class BinaryDiagnosticSerializer : public DiagnosticClient { + llvm::raw_ostream &OS; + SourceManager *SourceMgr; + public: + explicit BinaryDiagnosticSerializer(llvm::raw_ostream &OS) + : OS(OS), SourceMgr(0) { } + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); + }; +} + +void BinaryDiagnosticSerializer::HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info) { + Info.Serialize(DiagLevel, OS); +} static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts, unsigned argc, char **argv, @@ -122,8 +143,23 @@ Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, // Create the diagnostic client for reporting errors or for // implementing -verify. - llvm::OwningPtr<DiagnosticClient> DiagClient( - new TextDiagnosticPrinter(llvm::errs(), Opts)); + llvm::OwningPtr<DiagnosticClient> DiagClient; + if (Opts.BinaryOutput) { + if (llvm::sys::Program::ChangeStderrToBinary()) { + // We weren't able to set standard error to binary, which is a + // bit of a problem. So, just create a text diagnostic printer + // to complain about this problem, and pretend that the user + // didn't try to use binary output. + DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); + Diags->setClient(DiagClient.take()); + Diags->Report(diag::err_fe_stderr_binary); + return Diags.take(); + } else { + DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs())); + } + } else { + DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts)); + } // Chain in -verify checker, if requested. if (Opts.VerifyDiagnostics) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 0bca475..a193ac8 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -170,6 +170,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, } if (Opts.NoZeroInitializedInBSS) Res.push_back("-mno-zero-initialized-bss"); + if (Opts.ObjCLegacyDispatch) + Res.push_back("-fobjc-legacy-dispatch"); if (Opts.SoftFloat) Res.push_back("-msoft-float"); if (Opts.UnwindTables) @@ -178,6 +180,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-mrelocation-model"); Res.push_back(Opts.RelocationModel); } + if (!Opts.VerifyModule) + Res.push_back("-disable-llvm-verifier"); } static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts, @@ -220,6 +224,8 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, Res.push_back("-fcolor-diagnostics"); if (Opts.VerifyDiagnostics) Res.push_back("-verify"); + if (Opts.BinaryOutput) + Res.push_back("-fdiagnostics-binary"); if (Opts.ShowOptionNames) Res.push_back("-fdiagnostics-show-option"); if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) { @@ -276,6 +282,7 @@ static const char *getActionName(frontend::ActionKind Kind) { case frontend::EmitHTML: return "-emit-html"; case frontend::EmitLLVM: return "-emit-llvm"; case frontend::EmitLLVMOnly: return "-emit-llvm-only"; + case frontend::EmitObj: return "-emit-obj"; case frontend::FixIt: return "-fixit"; case frontend::GeneratePCH: return "-emit-pch"; case frontend::GeneratePTH: return "-emit-pth"; @@ -362,6 +369,10 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-load"); Res.push_back(Opts.Plugins[i]); } + for (unsigned i = 0, e = Opts.ASTMergeFiles.size(); i != e; ++i) { + Res.push_back("-ast-merge"); + Res.push_back(Opts.ASTMergeFiles[i]); + } } static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, @@ -450,6 +461,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fms-extensions"); if (Opts.ObjCNonFragileABI) Res.push_back("-fobjc-nonfragile-abi"); + if (Opts.ObjCNonFragileABI2) + Res.push_back("-fobjc-nonfragile-abi2"); // NoInline is implicit. if (!Opts.CXXOperatorNames) Res.push_back("-fno-operator-names"); @@ -465,6 +478,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-faltivec"); if (Opts.Exceptions) Res.push_back("-fexceptions"); + if (Opts.SjLjExceptions) + Res.push_back("-fsjlj-exceptions"); if (!Opts.RTTI) Res.push_back("-fno-rtti"); if (!Opts.NeXTRuntime) @@ -475,8 +490,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fno-builtin"); if (!Opts.AssumeSaneOperatorNew) Res.push_back("-fno-assume-sane-operator-new"); - if (Opts.ThreadsafeStatics) - llvm::llvm_report_error("FIXME: Not yet implemented!"); + if (!Opts.ThreadsafeStatics) + Res.push_back("-fno-threadsafe-statics"); if (Opts.POSIXThreads) Res.push_back("-pthread"); if (Opts.Blocks) @@ -770,18 +785,13 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.FloatABI = getLastArgValue(Args, OPT_mfloat_abi); Opts.LimitFloatPrecision = getLastArgValue(Args, OPT_mlimit_float_precision); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); + Opts.ObjCLegacyDispatch = Args.hasArg(OPT_fobjc_legacy_dispatch); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); Opts.RelocationModel = getLastArgValue(Args, OPT_mrelocation_model, "pic"); Opts.MainFileName = getLastArgValue(Args, OPT_main_file_name); - - // FIXME: Put elsewhere? -#ifdef NDEBUG - Opts.VerifyModule = 0; -#else - Opts.VerifyModule = 1; -#endif + Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); } static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, @@ -808,6 +818,7 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); + Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary); Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, DiagnosticOptions::DefaultTabStop, Diags); if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { @@ -852,6 +863,8 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { Opts.ProgramAction = frontend::EmitLLVM; break; case OPT_emit_llvm_only: Opts.ProgramAction = frontend::EmitLLVMOnly; break; + case OPT_emit_obj: + Opts.ProgramAction = frontend::EmitObj; break; case OPT_fixit: Opts.ProgramAction = frontend::FixIt; break; case OPT_emit_pch: @@ -920,6 +933,7 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { Opts.ShowTimers = Args.hasArg(OPT_ftime_report); Opts.ShowVersion = Args.hasArg(OPT_version); Opts.ViewClassInheritance = getLastArgValue(Args, OPT_cxx_inheritance_view); + Opts.ASTMergeFiles = getAllArgValues(Args, OPT_ast_merge); FrontendOptions::InputKind DashX = FrontendOptions::IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { @@ -1146,7 +1160,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.Microsoft = Args.hasArg(OPT_fms_extensions); Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); if (Args.hasArg(OPT_fno_lax_vector_conversions)) - Opts.LaxVectorConversions = 0; + Opts.LaxVectorConversions = 0; + if (Args.hasArg(OPT_fno_threadsafe_statics)) + Opts.ThreadsafeStatics = 0; Opts.Exceptions = Args.hasArg(OPT_fexceptions); Opts.RTTI = !Args.hasArg(OPT_fno_rtti); Opts.Blocks = Args.hasArg(OPT_fblocks); @@ -1165,10 +1181,15 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.ObjCConstantStringClass = getLastArgValue(Args, OPT_fconstant_string_class); Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); + Opts.ObjCNonFragileABI2 = Args.hasArg(OPT_fobjc_nonfragile_abi2); + if (Opts.ObjCNonFragileABI2) + Opts.ObjCNonFragileABI = true; Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); + Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); Opts.Static = Args.hasArg(OPT_static_define); + Opts.DumpVtableLayouts = Args.hasArg(OPT_fdump_vtable_layouts); Opts.OptimizeSize = 0; // FIXME: Eliminate this dependency. diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 0baba3f..1c958a7 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -177,6 +177,9 @@ ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, break; case Backend_EmitNothing: break; + case Backend_EmitObj: + OS.reset(CI.createDefaultOutputFile(true, InFile, "o")); + break; } if (BA != Backend_EmitNothing && !OS) return 0; @@ -196,6 +199,8 @@ EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {} EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {} +EmitObjAction::EmitObjAction() : CodeGenAction(Backend_EmitObj) {} + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp index b163e26..f695254 100644 --- a/lib/Frontend/HTMLDiagnostics.cpp +++ b/lib/Frontend/HTMLDiagnostics.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/PathDiagnosticClients.h" -#include "clang/Analysis/PathDiagnostic.h" +#include "clang/Checker/BugReporter/PathDiagnostic.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/Basic/SourceManager.h" diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 6102760..2e0b4bd 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -483,10 +483,10 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl AddPath("/usr/include/c++/4.1", System, true, false, false); break; case llvm::Triple::Linux: - // Exherbo (2009-10-26) - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", + // Exherbo (2010-01-25) + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3", "x86_64-pc-linux-gnu", "32", "", triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3", "i686-pc-linux-gnu", "", "", triple); // Debian sid AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", @@ -522,6 +522,10 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", "i686-redhat-linux","", "", triple); + // Fedora 12 (February-2010+) + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.3", + "i686-redhat-linux","", "", triple); + // openSUSE 11.1 32 bit AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", "i586-suse-linux", "", "", triple); diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 9aaf132..b7ab3d8 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -279,6 +279,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.Exceptions) Builder.defineMacro("__EXCEPTIONS"); + if (LangOpts.SjLjExceptions) + Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); if (LangOpts.CPlusPlus) { Builder.defineMacro("__DEPRECATED"); diff --git a/lib/Frontend/Makefile b/lib/Frontend/Makefile index 8d70847..a630b01 100644 --- a/lib/Frontend/Makefile +++ b/lib/Frontend/Makefile @@ -10,7 +10,6 @@ LEVEL = ../../../.. LIBRARYNAME := clangFrontend BUILD_ARCHIVE = 1 -CXXFLAGS = -fno-rtti CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 2593551..a878df7 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -72,12 +72,14 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c); PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2); PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); + PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2); PARSE_LANGOPT_BENIGN(PascalStrings); PARSE_LANGOPT_BENIGN(WritableStrings); PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, diag::warn_pch_lax_vector_conversions); PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec); PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions); + PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions); PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime); PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins); @@ -434,7 +436,9 @@ public: continue; } - Prev->Next = new ObjCMethodList(Method, 0); + ObjCMethodList *Mem = + Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); + Prev->Next = new (Mem) ObjCMethodList(Method, 0); Prev = Prev->Next; } @@ -450,7 +454,9 @@ public: continue; } - Prev->Next = new ObjCMethodList(Method, 0); + ObjCMethodList *Mem = + Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); + Prev->Next = new (Mem) ObjCMethodList(Method, 0); Prev = Prev->Next; } @@ -1326,6 +1332,14 @@ PCHReader::ReadPCHBlock() { TentativeDefinitions.swap(Record); break; + case pch::UNUSED_STATIC_FUNCS: + if (!UnusedStaticFuncs.empty()) { + Error("duplicate UNUSED_STATIC_FUNCS record in PCH file"); + return Failure; + } + UnusedStaticFuncs.swap(Record); + break; + case pch::LOCALLY_SCOPED_EXTERNAL_DECLS: if (!LocallyScopedExternalDecls.empty()) { Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file"); @@ -1400,9 +1414,9 @@ PCHReader::ReadPCHBlock() { break; case pch::VERSION_CONTROL_BRANCH_REVISION: { - llvm::StringRef CurBranch = getClangFullRepositoryVersion(); + const std::string &CurBranch = getClangFullRepositoryVersion(); llvm::StringRef PCHBranch(BlobStart, BlobLen); - if (CurBranch != PCHBranch) { + if (llvm::StringRef(CurBranch) != PCHBranch) { Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch; return IgnorePCH; } @@ -1740,11 +1754,13 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(ObjC1); PARSE_LANGOPT(ObjC2); PARSE_LANGOPT(ObjCNonFragileABI); + PARSE_LANGOPT(ObjCNonFragileABI2); PARSE_LANGOPT(PascalStrings); PARSE_LANGOPT(WritableStrings); PARSE_LANGOPT(LaxVectorConversions); PARSE_LANGOPT(AltiVec); PARSE_LANGOPT(Exceptions); + PARSE_LANGOPT(SjLjExceptions); PARSE_LANGOPT(NeXTRuntime); PARSE_LANGOPT(Freestanding); PARSE_LANGOPT(NoBuiltin); @@ -1880,18 +1896,20 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { } case pch::TYPE_VECTOR: { - if (Record.size() != 2) { + if (Record.size() != 4) { Error("incorrect encoding of vector type in PCH file"); return QualType(); } QualType ElementType = GetType(Record[0]); unsigned NumElements = Record[1]; - return Context->getVectorType(ElementType, NumElements); + bool AltiVec = Record[2]; + bool Pixel = Record[3]; + return Context->getVectorType(ElementType, NumElements, AltiVec, Pixel); } case pch::TYPE_EXT_VECTOR: { - if (Record.size() != 2) { + if (Record.size() != 4) { Error("incorrect encoding of extended vector type in PCH file"); return QualType(); } @@ -2464,11 +2482,17 @@ void PCHReader::InitializeSema(Sema &S) { PreloadedDecls.clear(); // If there were any tentative definitions, deserialize them and add - // them to Sema's table of tentative definitions. + // them to Sema's list of tentative definitions. for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I])); - SemaObj->TentativeDefinitions[Var->getDeclName()] = Var; - SemaObj->TentativeDefinitionList.push_back(Var->getDeclName()); + SemaObj->TentativeDefinitions.push_back(Var); + } + + // If there were any unused static functions, deserialize them and add to + // Sema's list of unused static functions. + for (unsigned I = 0, N = UnusedStaticFuncs.size(); I != N; ++I) { + FunctionDecl *FD = cast<FunctionDecl>(GetDecl(UnusedStaticFuncs[I])); + SemaObj->UnusedStaticFuncs.push_back(FD); } // If there were any locally-scoped external declarations, diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 4dc1318..625997c 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -117,6 +117,7 @@ void PCHDeclReader::VisitTagDecl(TagDecl *TD) { cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++]))); TD->setTagKind((TagDecl::TagKind)Record[Idx++]); TD->setDefinition(Record[Idx++]); + TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setTypedefForAnonDecl( cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++]))); TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -179,7 +180,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - FD->setParams(*Reader.getContext(), Params.data(), NumParams); + FD->setParams(Params.data(), NumParams); } void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { @@ -387,7 +388,7 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) { VD->setPreviousDeclaration( cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); if (Record[Idx++]) - VD->setInit(*Reader.getContext(), Reader.ReadDeclExpr()); + VD->setInit(Reader.ReadDeclExpr()); } void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { @@ -412,7 +413,7 @@ void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) { Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - BD->setParams(*Reader.getContext(), Params.data(), NumParams); + BD->setParams(Params.data(), NumParams); } std::pair<uint64_t, uint64_t> @@ -445,7 +446,7 @@ Attr *PCHReader::ReadAttributes() { #define STRING_ATTR(Name) \ case Attr::Name: \ - New = ::new (*Context) Name##Attr(ReadString(Record, Idx)); \ + New = ::new (*Context) Name##Attr(*Context, ReadString(Record, Idx)); \ break #define UNSIGNED_ATTR(Name) \ @@ -496,7 +497,7 @@ Attr *PCHReader::ReadAttributes() { std::string Type = ReadString(Record, Idx); unsigned FormatIdx = Record[Idx++]; unsigned FirstArg = Record[Idx++]; - New = ::new (*Context) FormatAttr(Type, FormatIdx, FirstArg); + New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg); break; } @@ -531,7 +532,7 @@ Attr *PCHReader::ReadAttributes() { llvm::SmallVector<unsigned, 16> ArgNums; ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size); Idx += Size; - New = ::new (*Context) NonNullAttr(ArgNums.data(), Size); + New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size); break; } diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 21c9cbf..d123694 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -123,6 +123,8 @@ namespace { unsigned VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E); unsigned VisitCXXConstCastExpr(CXXConstCastExpr *E); unsigned VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E); + unsigned VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); + unsigned VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); }; } @@ -317,22 +319,24 @@ unsigned PCHStmtReader::VisitAsmStmt(AsmStmt *S) { S->setAsmString(cast_or_null<StringLiteral>(StmtStack[StackIdx++])); // Outputs and inputs - llvm::SmallVector<std::string, 16> Names; + llvm::SmallVector<IdentifierInfo *, 16> Names; llvm::SmallVector<StringLiteral*, 16> Constraints; llvm::SmallVector<Stmt*, 16> Exprs; for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) { - Names.push_back(Reader.ReadString(Record, Idx)); + Names.push_back(Reader.GetIdentifierInfo(Record, Idx)); Constraints.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++])); Exprs.push_back(StmtStack[StackIdx++]); } - S->setOutputsAndInputs(NumOutputs, NumInputs, - Names.data(), Constraints.data(), Exprs.data()); // Constraints llvm::SmallVector<StringLiteral*, 16> Clobbers; for (unsigned I = 0; I != NumClobbers; ++I) Clobbers.push_back(cast_or_null<StringLiteral>(StmtStack[StackIdx++])); - S->setClobbers(Clobbers.data(), NumClobbers); + + S->setOutputsAndInputsAndClobbers(*Reader.getContext(), + Names.data(), Constraints.data(), + Exprs.data(), NumOutputs, NumInputs, + Clobbers.data(), NumClobbers); assert(StackIdx == StmtStack.size() && "Error deserializing AsmStmt"); return NumOutputs*2 + NumInputs*2 + NumClobbers + 1; @@ -904,6 +908,19 @@ unsigned PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { return num; } +unsigned PCHStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + VisitExpr(E); + E->setValue(Record[Idx++]); + E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); + return 0; +} + +unsigned PCHStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { + VisitExpr(E); + E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); + return 0; +} + // Within the bitstream, expressions are stored in Reverse Polish // Notation, with each of the subexpressions preceding the // expression they are stored in. To evaluate expressions, we @@ -1233,7 +1250,13 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { S = new (Context) CXXFunctionalCastExpr(Empty); break; + case pch::EXPR_CXX_BOOL_LITERAL: + S = new (Context) CXXBoolLiteralExpr(Empty); + break; + case pch::EXPR_CXX_NULL_PTR_LITERAL: + S = new (Context) CXXNullPtrLiteralExpr(Empty); + break; } // We hit a STMT_STOP, so we're done with this expression. diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 9909c95..4c99dbe 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -128,6 +128,8 @@ void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { void PCHTypeWriter::VisitVectorType(const VectorType *T) { Writer.AddTypeRef(T->getElementType(), Record); Record.push_back(T->getNumElements()); + Record.push_back(T->isAltiVec()); + Record.push_back(T->isPixel()); Code = pch::TYPE_VECTOR; } @@ -511,6 +513,15 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(STMT_OBJC_AT_TRY); RECORD(STMT_OBJC_AT_SYNCHRONIZED); RECORD(STMT_OBJC_AT_THROW); + RECORD(EXPR_CXX_OPERATOR_CALL); + RECORD(EXPR_CXX_CONSTRUCT); + RECORD(EXPR_CXX_STATIC_CAST); + RECORD(EXPR_CXX_DYNAMIC_CAST); + RECORD(EXPR_CXX_REINTERPRET_CAST); + RECORD(EXPR_CXX_CONST_CAST); + RECORD(EXPR_CXX_FUNCTIONAL_CAST); + RECORD(EXPR_CXX_BOOL_LITERAL); + RECORD(EXPR_CXX_NULL_PTR_LITERAL); #undef RECORD } @@ -534,6 +545,7 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(SPECIAL_TYPES); RECORD(STATISTICS); RECORD(TENTATIVE_DEFINITIONS); + RECORD(UNUSED_STATIC_FUNCS); RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS); RECORD(SELECTOR_OFFSETS); RECORD(METHOD_POOL); @@ -737,13 +749,17 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled. Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled. - Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C modern abi enabled + Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C + // modern abi enabled. + Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced + // modern abi enabled. Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings Record.push_back(LangOpts.WritableStrings); // Allow writable strings Record.push_back(LangOpts.LaxVectorConversions); Record.push_back(LangOpts.AltiVec); Record.push_back(LangOpts.Exceptions); // Support exception handling. + Record.push_back(LangOpts.SjLjExceptions); Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime. Record.push_back(LangOpts.Freestanding); // Freestanding implementation @@ -1960,15 +1976,18 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, } // Build a record containing all of the tentative definitions in this file, in - // TentativeDefinitionList order. Generally, this record will be empty for + // TentativeDefinitions order. Generally, this record will be empty for // headers. RecordData TentativeDefinitions; - for (unsigned i = 0, e = SemaRef.TentativeDefinitionList.size(); i != e; ++i){ - VarDecl *VD = - SemaRef.TentativeDefinitions.lookup(SemaRef.TentativeDefinitionList[i]); - if (VD) AddDeclRef(VD, TentativeDefinitions); + for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) { + AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions); } + // Build a record containing all of the static unused functions in this file. + RecordData UnusedStaticFuncs; + for (unsigned i=0, e = SemaRef.UnusedStaticFuncs.size(); i !=e; ++i) + AddDeclRef(SemaRef.UnusedStaticFuncs[i], UnusedStaticFuncs); + // Build a record containing all of the locally-scoped external // declarations in this header file. Generally, this record will be // empty. @@ -2070,6 +2089,10 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, if (!TentativeDefinitions.empty()) Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions); + // Write the record containing unused static functions. + if (!UnusedStaticFuncs.empty()) + Stream.EmitRecord(pch::UNUSED_STATIC_FUNCS, UnusedStaticFuncs); + // Write the record containing locally-scoped external definitions. if (!LocallyScopedExternalDecls.empty()) Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS, diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 020f69b..d105382 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -115,6 +115,7 @@ void PCHDeclWriter::VisitTagDecl(TagDecl *D) { Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding Record.push_back(D->isDefinition()); + Record.push_back(D->isEmbeddedInDeclarator()); Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); Writer.AddSourceLocation(D->getRBraceLoc(), Record); Writer.AddSourceLocation(D->getTagKeywordLoc(), Record); diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index fdfdfef..a8cc9d6 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -118,6 +118,8 @@ namespace { void VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E); void VisitCXXConstCastExpr(CXXConstCastExpr *E); void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E); + void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E); + void VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E); }; } @@ -287,15 +289,15 @@ void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) { Writer.WriteSubStmt(S->getAsmString()); // Outputs - for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { - Writer.AddString(S->getOutputName(I), Record); + for (unsigned I = 0, N = S->getNumOutputs(); I != N; ++I) { + Writer.AddIdentifierRef(S->getOutputIdentifier(I), Record); Writer.WriteSubStmt(S->getOutputConstraintLiteral(I)); Writer.WriteSubStmt(S->getOutputExpr(I)); } // Inputs for (unsigned I = 0, N = S->getNumInputs(); I != N; ++I) { - Writer.AddString(S->getInputName(I), Record); + Writer.AddIdentifierRef(S->getInputIdentifier(I), Record); Writer.WriteSubStmt(S->getInputConstraintLiteral(I)); Writer.WriteSubStmt(S->getInputExpr(I)); } @@ -834,6 +836,19 @@ void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { Code = pch::EXPR_CXX_FUNCTIONAL_CAST; } +void PCHStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + VisitExpr(E); + Record.push_back(E->getValue()); + Writer.AddSourceLocation(E->getLocation(), Record); + Code = pch::EXPR_CXX_BOOL_LITERAL; +} + +void PCHStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { + VisitExpr(E); + Writer.AddSourceLocation(E->getLocation(), Record); + Code = pch::EXPR_CXX_NULL_PTR_LITERAL; +} + //===----------------------------------------------------------------------===// // PCHWriter Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp index 98be869..5706a07 100644 --- a/lib/Frontend/PlistDiagnostics.cpp +++ b/lib/Frontend/PlistDiagnostics.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/PathDiagnosticClients.h" -#include "clang/Analysis/PathDiagnostic.h" +#include "clang/Checker/BugReporter/PathDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/Lex/Preprocessor.h" diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index a91dd8d..8d64a64 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -391,7 +391,7 @@ namespace { bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, - std::string *Names, + IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, ExprArg AsmString, @@ -684,7 +684,8 @@ namespace { virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, IdentifierInfo *Ident, - SourceLocation LBrace) { + SourceLocation LBrace, + AttributeList *AttrList) { Out << __FUNCTION__ << "\n"; return DeclPtrTy(); } diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index 35d8dde..9dade66 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -124,8 +124,10 @@ namespace { llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs; // Block related declarations. - llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls; - llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls; + llvm::SmallVector<ValueDecl *, 8> BlockByCopyDecls; + llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; + llvm::SmallVector<ValueDecl *, 8> BlockByRefDecls; + llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; @@ -212,11 +214,10 @@ namespace { << Old->getSourceRange(); } - void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen, + void InsertText(SourceLocation Loc, llvm::StringRef Str, bool InsertAfter = true) { // If insertion succeeded or warning disabled return with no warning. - if (!Rewrite.InsertText(Loc, llvm::StringRef(StrData, StrLen), - InsertAfter) || + if (!Rewrite.InsertText(Loc, Str, InsertAfter) || SilenceRewriteMacroWarning) return; @@ -232,10 +233,9 @@ namespace { } void ReplaceText(SourceLocation Start, unsigned OrigLength, - const char *NewStr, unsigned NewLength) { + llvm::StringRef Str) { // If removal succeeded or warning disabled return with no warning. - if (!Rewrite.ReplaceText(Start, OrigLength, - llvm::StringRef(NewStr, NewLength)) || + if (!Rewrite.ReplaceText(Start, OrigLength, Str) || SilenceRewriteMacroWarning) return; @@ -263,6 +263,7 @@ namespace { void RewriteFunctionDecl(FunctionDecl *FD); void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); + void RewriteTypeOfDecl(VarDecl *VD); void RewriteObjCQualifiedInterfaceTypes(Expr *E); bool needToScanForQualifiers(QualType T); ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr); @@ -278,7 +279,9 @@ namespace { ParentMap *PropParentMap; // created lazily. Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); - Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart); + Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart, + bool &replaced); + Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced); Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr); Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, SourceRange SrcRange); @@ -632,6 +635,9 @@ void RewriteObjC::Initialize(ASTContext &context) { //===----------------------------------------------------------------------===// void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { + if (Diags.hasErrorOccurred()) + return; + // Two cases: either the decl could be in the main file, or it could be in a // #included file. If the former, rewrite it now. If the later, check to see // if we rewrote the #include/#import. @@ -681,7 +687,6 @@ void RewriteObjC::RewriteInclude() { const char *MainBufStart = MainBuf.first; const char *MainBufEnd = MainBuf.second; size_t ImportLen = strlen("import"); - size_t IncludeLen = strlen("include"); // Loop over the whole file, looking for includes. for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { @@ -695,7 +700,7 @@ void RewriteObjC::RewriteInclude() { // replace import with include SourceLocation ImportLoc = LocStart.getFileLocWithOffset(BufPtr-MainBufStart); - ReplaceText(ImportLoc, ImportLen, "include", IncludeLen); + ReplaceText(ImportLoc, ImportLen, "include"); BufPtr += ImportLen; } } @@ -728,7 +733,7 @@ void RewriteObjC::RewriteTabs() { TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart); // Rewrite the single tab character into a sequence of spaces. - ReplaceText(TabLoc, 1, " ", Spaces); + ReplaceText(TabLoc, 1, llvm::StringRef(" ", Spaces)); } } @@ -746,7 +751,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, ObjCImplementationDecl *IMD, ObjCCategoryImplDecl *CID) { SourceLocation startLoc = PID->getLocStart(); - InsertText(startLoc, "// ", 3); + InsertText(startLoc, "// "); const char *startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '@') && "bogus @synthesize location"); const char *semiBuf = strchr(startBuf, ';'); @@ -774,7 +779,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, // See objc-act.c:objc_synthesize_new_getter() for details. Getr += "return " + getIvarAccessString(ClassDecl, OID); Getr += "; }"; - InsertText(onePastSemiLoc, Getr.c_str(), Getr.size()); + InsertText(onePastSemiLoc, Getr); if (PD->isReadOnly()) return; @@ -789,7 +794,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, Setr += getIvarAccessString(ClassDecl, OID) + " = "; Setr += PD->getNameAsCString(); Setr += "; }"; - InsertText(onePastSemiLoc, Setr.c_str(), Setr.size()); + InsertText(onePastSemiLoc, Setr); } void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { @@ -828,8 +833,7 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { } // Replace the @class with typedefs corresponding to the classes. - ReplaceText(startLoc, semiPtr-startBuf+1, - typedefString.c_str(), typedefString.size()); + ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); } void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { @@ -842,17 +846,17 @@ void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { if (SM->getInstantiationLineNumber(LocEnd) > SM->getInstantiationLineNumber(LocStart)) { - InsertText(LocStart, "#if 0\n", 6); - ReplaceText(LocEnd, 1, ";\n#endif\n", 9); + InsertText(LocStart, "#if 0\n"); + ReplaceText(LocEnd, 1, ";\n#endif\n"); } else { - InsertText(LocStart, "// ", 3); + InsertText(LocStart, "// "); } } void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { SourceLocation Loc = prop->getAtLoc(); - ReplaceText(Loc, 0, "// ", 3); + ReplaceText(Loc, 0, "// "); // FIXME: handle properties that are declared across multiple lines. } @@ -860,8 +864,12 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { SourceLocation LocStart = CatDecl->getLocStart(); // FIXME: handle category headers that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); + ReplaceText(LocStart, 0, "// "); + for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), + E = CatDecl->prop_end(); I != E; ++I) + RewriteProperty(*I); + for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); I != E; ++I) @@ -872,7 +880,7 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { RewriteMethodDeclaration(*I); // Lastly, comment out the @end. - ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// ", 3); + ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// "); } void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { @@ -881,7 +889,7 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { SourceLocation LocStart = PDecl->getLocStart(); // FIXME: handle protocol headers that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); + ReplaceText(LocStart, 0, "// "); for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); @@ -894,24 +902,20 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { // Lastly, comment out the @end. SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); - ReplaceText(LocEnd, 0, "// ", 3); + ReplaceText(LocEnd, 0, "// "); // Must comment out @optional/@required const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); for (const char *p = startBuf; p < endBuf; p++) { if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { - std::string CommentedOptional = "/* @optional */"; SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); - ReplaceText(OptionalLoc, strlen("@optional"), - CommentedOptional.c_str(), CommentedOptional.size()); + ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); } else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { - std::string CommentedRequired = "/* @required */"; SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); - ReplaceText(OptionalLoc, strlen("@required"), - CommentedRequired.c_str(), CommentedRequired.size()); + ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); } } @@ -922,7 +926,7 @@ void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) { if (LocStart.isInvalid()) assert(false && "Invalid SourceLocation"); // FIXME: handle forward protocol that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); + ReplaceText(LocStart, 0, "// "); } void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, @@ -1050,10 +1054,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); - if (IMD) - InsertText(IMD->getLocStart(), "// ", 3); - else - InsertText(CID->getLocStart(), "// ", 3); + InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// "); for (ObjCCategoryImplDecl::instmeth_iterator I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), @@ -1067,8 +1068,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); - ReplaceText(LocStart, endBuf-startBuf, - ResultStr.c_str(), ResultStr.size()); + ReplaceText(LocStart, endBuf-startBuf, ResultStr); } for (ObjCCategoryImplDecl::classmeth_iterator @@ -1083,8 +1083,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); - ReplaceText(LocStart, endBuf-startBuf, - ResultStr.c_str(), ResultStr.size()); + ReplaceText(LocStart, endBuf-startBuf, ResultStr); } for (ObjCCategoryImplDecl::propimpl_iterator I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), @@ -1093,10 +1092,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { RewritePropertyImplDecl(*I, IMD, CID); } - if (IMD) - InsertText(IMD->getLocEnd(), "// ", 3); - else - InsertText(CID->getLocEnd(), "// ", 3); + InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); } void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { @@ -1130,7 +1126,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { RewriteMethodDeclaration(*I); // Lastly, comment out the @end. - ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// ", 3); + ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// "); } Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, @@ -1149,7 +1145,7 @@ Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), + MsgExpr = new (Context) ObjCMessageExpr(*Context, dyn_cast<Expr>(Receiver), PDecl->getSetterName(), PDecl->getType(), PDecl->getSetterMethodDecl(), SourceLocation(), SourceLocation(), @@ -1178,7 +1174,7 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), + MsgExpr = new (Context) ObjCMessageExpr(*Context, dyn_cast<Expr>(Receiver), PDecl->getGetterName(), PDecl->getType(), PDecl->getGetterMethodDecl(), SourceLocation(), SourceLocation(), @@ -1209,14 +1205,15 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { } Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, - SourceLocation OrigStart) { + SourceLocation OrigStart, + bool &replaced) { ObjCIvarDecl *D = IV->getDecl(); const Expr *BaseExpr = IV->getBase(); if (CurMethodDef) { - if (BaseExpr->getType()->isObjCObjectPointerType() && - isa<DeclRefExpr>(BaseExpr)) { + if (BaseExpr->getType()->isObjCObjectPointerType()) { ObjCInterfaceType *iFaceDecl = dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); + assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); // lookup which class implements the instance variable. ObjCInterfaceDecl *clsDeclared = 0; iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), @@ -1226,7 +1223,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // Synthesize an explicit cast to gain access to the ivar. std::string RecName = clsDeclared->getIdentifier()->getName(); RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName.c_str()); + IdentifierInfo *II = &Context->Idents.get(RecName); RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, SourceLocation(), II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); @@ -1238,17 +1235,16 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), IV->getBase()->getLocEnd(), castExpr); + replaced = true; if (IV->isFreeIvar() && CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) { MemberExpr *ME = new (Context) MemberExpr(PE, true, D, IV->getLocation(), D->getType()); - ReplaceStmt(IV, ME); // delete IV; leak for now, see RewritePropertySetter() usage for more info. return ME; } - - ReplaceStmt(IV->getBase(), PE); + // Get the new text // Cannot delete IV->getBase(), since PE points to it. // Replace the old base with the cast. This is important when doing // embedded rewrites. For example, [newInv->_container addObject:0]. @@ -1272,7 +1268,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // Synthesize an explicit cast to gain access to the ivar. std::string RecName = clsDeclared->getIdentifier()->getName(); RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName.c_str()); + IdentifierInfo *II = &Context->Idents.get(RecName); RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, SourceLocation(), II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); @@ -1283,7 +1279,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // Don't forget the parens to enforce the proper binding. ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), IV->getBase()->getLocEnd(), castExpr); - ReplaceStmt(IV->getBase(), PE); + replaced = true; // Cannot delete IV->getBase(), since PE points to it. // Replace the old base with the cast. This is important when doing // embedded rewrites. For example, [newInv->_container addObject:0]. @@ -1294,6 +1290,28 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, return IV; } +Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) { + for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); + CI != E; ++CI) { + if (*CI) { + Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced); + if (newStmt) + *CI = newStmt; + } + } + if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { + SourceRange OrigStmtRange = S->getSourceRange(); + Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(), + replaced); + return newStmt; + } + if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) { + Stmt *newStmt = SynthMessageExpr(MsgRefExpr); + return newStmt; + } + return S; +} + /// SynthCountByEnumWithState - To print: /// ((unsigned int (*) /// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) @@ -1326,7 +1344,7 @@ Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { SourceLocation startLoc = S->getLocStart(); buf = "goto __break_label_"; buf += utostr(ObjCBcLabelNo.back()); - ReplaceText(startLoc, strlen("break"), buf.c_str(), buf.size()); + ReplaceText(startLoc, strlen("break"), buf); return 0; } @@ -1343,7 +1361,7 @@ Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { SourceLocation startLoc = S->getLocStart(); buf = "goto __continue_label_"; buf += utostr(ObjCBcLabelNo.back()); - ReplaceText(startLoc, strlen("continue"), buf.c_str(), buf.size()); + ReplaceText(startLoc, strlen("continue"), buf); return 0; } @@ -1442,8 +1460,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, startCollectionBuf += 3; // Replace: "for (type element in" with string constructed thus far. - ReplaceText(startLoc, startCollectionBuf - startBuf, - buf.c_str(), buf.size()); + ReplaceText(startLoc, startCollectionBuf - startBuf, buf); // Replace ')' in for '(' type elem in collection ')' with ';' SourceLocation rightParenLoc = S->getRParenLoc(); const char *rparenBuf = SM->getCharacterData(rightParenLoc); @@ -1484,7 +1501,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, buf += elementTypeAsString; buf += ")enumState.itemsPtr[counter++];"; // Replace ')' in for '(' type elem in collection ')' with all of these. - ReplaceText(lparenLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lparenLoc, 1, buf); /// __continue_label: ; /// } while (counter < limit); @@ -1525,7 +1542,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, // FIXME: If this should support Obj-C++, support CXXTryStmt if (isa<CompoundStmt>(S->getBody())) { SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1); - InsertText(endBodyLoc, buf.c_str(), buf.size()); + InsertText(endBodyLoc, buf); } else { /* Need to treat single statements specially. For example: * @@ -1538,7 +1555,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, const char *semiBuf = strchr(stmtBuf, ';'); assert(semiBuf && "Can't find ';'"); SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1); - InsertText(endBodyLoc, buf.c_str(), buf.size()); + InsertText(endBodyLoc, buf); } Stmts.pop_back(); ObjCBcLabelNo.pop_back(); @@ -1562,7 +1579,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf = "objc_sync_enter((id)"; const char *lparenBuf = startBuf; while (*lparenBuf != '(') lparenBuf++; - ReplaceText(startLoc, lparenBuf-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, lparenBuf-startBuf+1, buf); // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since // the sync expression is typically a message expression that's already // been rewritten! (which implies the SourceLocation's are invalid). @@ -1578,7 +1595,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf += "id volatile _rethrow = 0;\n"; buf += "objc_exception_try_enter(&_stack);\n"; buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; - ReplaceText(rparenLoc, 1, buf.c_str(), buf.size()); + ReplaceText(rparenLoc, 1, buf); startLoc = S->getSynchBody()->getLocEnd(); startBuf = SM->getCharacterData(startLoc); @@ -1607,7 +1624,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf += "}\n"; buf += "}"; - ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lastCurlyLoc, 1, buf); bool hasReturns = false; HasReturnStmts(S->getSynchBody(), hasReturns); @@ -1663,8 +1680,8 @@ void RewriteObjC::RewriteTryReturnStmts(Stmt *S) { std::string buf; buf = "{ objc_exception_try_exit(&_stack); return"; - ReplaceText(startLoc, 6, buf.c_str(), buf.size()); - InsertText(onePastSemiLoc, "}", 1); + ReplaceText(startLoc, 6, buf); + InsertText(onePastSemiLoc, "}"); } return; } @@ -1689,8 +1706,8 @@ void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) { buf += syncExitBuf; buf += " return"; - ReplaceText(startLoc, 6, buf.c_str(), buf.size()); - InsertText(onePastSemiLoc, "}", 1); + ReplaceText(startLoc, 6, buf); + InsertText(onePastSemiLoc, "}"); } return; } @@ -1711,7 +1728,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "objc_exception_try_enter(&_stack);\n"; buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; - ReplaceText(startLoc, 4, buf.c_str(), buf.size()); + ReplaceText(startLoc, 4, buf); startLoc = S->getTryBody()->getLocEnd(); startBuf = SM->getCharacterData(startLoc); @@ -1729,12 +1746,12 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += " _rethrow = objc_exception_extract(&_stack);\n"; buf += " else { /* @catch continue */"; - InsertText(startLoc, buf.c_str(), buf.size()); + InsertText(startLoc, buf); } else { /* no catch list */ buf = "}\nelse {\n"; buf += " _rethrow = objc_exception_extract(&_stack);\n"; buf += "}"; - ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lastCurlyLoc, 1, buf); } bool sawIdTypedCatch = false; Stmt *lastCatchBody = 0; @@ -1767,7 +1784,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { QualType t = catchDecl->getType(); if (t == Context->getObjCIdType()) { buf += "1) { "; - ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, lParenLoc-startBuf+1, buf); sawIdTypedCatch = true; } else if (t->isObjCObjectPointerType()) { QualType InterfaceTy = t->getPointeeType(); @@ -1777,7 +1794,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; buf += cls->getDecl()->getNameAsString(); buf += "\"), (struct objc_object *)_caught)) { "; - ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, lParenLoc-startBuf+1, buf); } } // Now rewrite the body... @@ -1789,10 +1806,9 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { assert((*rParenBuf == ')') && "bogus @catch paren location"); assert((*bodyBuf == '{') && "bogus @catch body location"); - buf = " = _caught;"; // Here we replace ") {" with "= _caught;" (which initializes and // declares the @catch parameter). - ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size()); + ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;"); } else { assert(false && "@catch rewrite bug"); } @@ -1814,7 +1830,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "} } /* @catch end */\n"; if (!S->getFinallyStmt()) buf += "}\n"; - InsertText(bodyLoc, buf.c_str(), buf.size()); + InsertText(bodyLoc, buf); // Set lastCurlyLoc lastCurlyLoc = lastCatchBody->getLocEnd(); @@ -1824,8 +1840,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '@') && "bogus @finally start"); - buf = "/* @finally */"; - ReplaceText(startLoc, 8, buf.c_str(), buf.size()); + ReplaceText(startLoc, 8, "/* @finally */"); Stmt *body = finalStmt->getFinallyBody(); SourceLocation startLoc = body->getLocStart(); @@ -1836,11 +1851,9 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { "bogus @finally body location"); startLoc = startLoc.getFileLocWithOffset(1); - buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; - InsertText(startLoc, buf.c_str(), buf.size()); + InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n"); endLoc = endLoc.getFileLocWithOffset(-1); - buf = " if (_rethrow) objc_exception_throw(_rethrow);\n"; - InsertText(endLoc, buf.c_str(), buf.size()); + InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n"); // Set lastCurlyLoc lastCurlyLoc = body->getLocEnd(); @@ -1852,7 +1865,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; buf += "}"; - ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lastCurlyLoc, 1, buf); // Now check for any return/continue/go statements within the @try. // The implicit finally clause won't called if the @try contains any @@ -1864,8 +1877,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } // Now emit the final closing curly brace... lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1); - buf = " } /* @try scope end */\n"; - InsertText(lastCurlyLoc, buf.c_str(), buf.size()); + InsertText(lastCurlyLoc, " } /* @try scope end */\n"); return 0; } @@ -1897,13 +1909,12 @@ Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { // handle "@ throw" correctly. const char *wBuf = strchr(startBuf, 'w'); assert((*wBuf == 'w') && "@throw: can't find 'w'"); - ReplaceText(startLoc, wBuf-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, wBuf-startBuf+1, buf); const char *semiBuf = strchr(startBuf, ';'); assert((*semiBuf == ';') && "@throw: can't find ';'"); SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf); - buf = ");"; - ReplaceText(semiLoc, 1, buf.c_str(), buf.size()); + ReplaceText(semiLoc, 1, ");"); return 0; } @@ -1991,7 +2002,17 @@ static void scanToNextArgument(const char *&argRef) { } bool RewriteObjC::needToScanForQualifiers(QualType T) { - return T->isObjCQualifiedIdType() || T->isObjCQualifiedInterfaceType(); + if (T->isObjCQualifiedIdType()) + return true; + if (const PointerType *PT = T->getAs<PointerType>()) { + if (PT->getPointeeType()->isObjCQualifiedIdType()) + return true; + } + if (T->isObjCObjectPointerType()) { + T = T->getPointeeType(); + return T->isObjCQualifiedInterfaceType(); + } + return false; } void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { @@ -2018,8 +2039,8 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf); SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1); // Comment out the protocol references. - InsertText(LessLoc, "/*", 2); - InsertText(GreaterLoc, "*/", 2); + InsertText(LessLoc, "/*"); + InsertText(GreaterLoc, "*/"); } } } @@ -2063,8 +2084,8 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf); SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1); // Comment out the protocol references. - InsertText(LessLoc, "/*", 2); - InsertText(GreaterLoc, "*/", 2); + InsertText(LessLoc, "/*"); + InsertText(GreaterLoc, "*/"); } } if (!proto) @@ -2087,8 +2108,8 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startFuncBuf+1); // Comment out the protocol references. - InsertText(LessLoc, "/*", 2); - InsertText(GreaterLoc, "*/", 2); + InsertText(LessLoc, "/*"); + InsertText(GreaterLoc, "*/"); } startBuf = ++endBuf; } @@ -2102,6 +2123,42 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { } } +void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) { + QualType QT = ND->getType(); + const Type* TypePtr = QT->getAs<Type>(); + if (!isa<TypeOfExprType>(TypePtr)) + return; + while (isa<TypeOfExprType>(TypePtr)) { + const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); + QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); + TypePtr = QT->getAs<Type>(); + } + // FIXME. This will not work for multiple declarators; as in: + // __typeof__(a) b,c,d; + std::string TypeAsString(QT.getAsString()); + SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); + const char *startBuf = SM->getCharacterData(DeclLoc); + if (ND->getInit()) { + std::string Name(ND->getNameAsString()); + TypeAsString += " " + Name + " = "; + Expr *E = ND->getInit(); + SourceLocation startLoc; + if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) + startLoc = ECE->getLParenLoc(); + else + startLoc = E->getLocStart(); + startLoc = SM->getInstantiationLoc(startLoc); + const char *endBuf = SM->getCharacterData(startLoc); + ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); + } + else { + SourceLocation X = ND->getLocEnd(); + X = SM->getInstantiationLoc(X); + const char *endBuf = SM->getCharacterData(X); + ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); + } +} + // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); void RewriteObjC::SynthSelGetUidFunctionDecl() { IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); @@ -2126,6 +2183,19 @@ void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { RewriteObjCQualifiedInterfaceTypes(FD); } +static void RewriteBlockPointerType(std::string& Str, QualType Type) { + std::string TypeString(Type.getAsString()); + const char *argPtr = TypeString.c_str(); + if (!strchr(argPtr, '^')) { + Str += TypeString; + return; + } + while (*argPtr) { + Str += (*argPtr == '^' ? '*' : *argPtr); + argPtr++; + } +} + void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); @@ -2140,13 +2210,12 @@ void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { unsigned numArgs = proto->getNumArgs(); for (unsigned i = 0; i < numArgs; i++) { QualType ArgType = proto->getArgType(i); - FdStr += ArgType.getAsString(); - + RewriteBlockPointerType(FdStr, ArgType); if (i+1 < numArgs) FdStr += ", "; } FdStr += ");\n"; - InsertText(FunLocStart, FdStr.c_str(), FdStr.size()); + InsertText(FunLocStart, FdStr); CurFunctionDeclToDeclareForBlock = 0; } @@ -2330,7 +2399,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - &Context->Idents.get(S.c_str()), strType, 0, + &Context->Idents.get(S), strType, 0, VarDecl::Static); DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation()); Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, @@ -2380,7 +2449,7 @@ QualType RewriteObjC::getSuperStructType() { /*Mutable=*/false)); } - SuperStructDecl->completeDefinition(*Context); + SuperStructDecl->completeDefinition(); } return Context->getTagDeclType(SuperStructDecl); } @@ -2411,7 +2480,7 @@ QualType RewriteObjC::getConstantStringStructType() { /*Mutable=*/true)); } - ConstantStringDecl->completeDefinition(*Context); + ConstantStringDecl->completeDefinition(); } return Context->getTagDeclType(ConstantStringDecl); } @@ -2871,7 +2940,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, if ((CDecl->isForwardDecl() || NumIvars == 0) && (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); - ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, endBuf-startBuf, Result); return; } @@ -2913,10 +2982,10 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, endHeader++; } // rewrite the original header - ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, endHeader-startBuf, Result); } else { // rewrite the original header *without* disturbing the '{' - ReplaceText(LocStart, cursor-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, cursor-startBuf, Result); } if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { Result = "\n struct "; @@ -2928,7 +2997,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, // insert the super class structure definition. SourceLocation OnePastCurly = LocStart.getFileLocWithOffset(cursor-startBuf+1); - InsertText(OnePastCurly, Result.c_str(), Result.size()); + InsertText(OnePastCurly, Result); } cursor++; // past '{' @@ -2946,26 +3015,26 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, !strncmp(cursor, "private", strlen("private")) || !strncmp(cursor, "package", strlen("package")) || !strncmp(cursor, "protected", strlen("protected"))) - InsertText(atLoc, "// ", 3); + InsertText(atLoc, "// "); } // FIXME: If there are cases where '<' is used in ivar declaration part // of user code, then scan the ivar list and use needToScanForQualifiers // for type checking. else if (*cursor == '<') { SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); - InsertText(atLoc, "/* ", 3); + InsertText(atLoc, "/* "); cursor = strchr(cursor, '>'); cursor++; atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); - InsertText(atLoc, " */", 3); + InsertText(atLoc, " */"); } else if (*cursor == '^') { // rewrite block specifier. SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf); - ReplaceText(caretLoc, 1, "*", 1); + ReplaceText(caretLoc, 1, "*"); } cursor++; } // Don't forget to add a ';'!! - InsertText(LocEnd.getFileLocWithOffset(1), ";", 1); + InsertText(LocEnd.getFileLocWithOffset(1), ";"); } else { // we don't have any instance variables - insert super struct. endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); Result += " {\n struct "; @@ -2973,7 +3042,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, Result += "_IMPL "; Result += RCDecl->getNameAsString(); Result += "_IVARS;\n};\n"; - ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, endBuf-startBuf, Result); } // Mark this struct as having been generated. if (!ObjCSynthesizedStructs.insert(CDecl)) @@ -3805,7 +3874,7 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, // Create local declarations to avoid rewriting all closure decl ref exprs. // First, emit a declaration for all "by ref" decls. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); @@ -3816,7 +3885,7 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; } // Next, emit a declaration for all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); @@ -3861,7 +3930,7 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, S += (*I)->getNameAsString(); S += ", (void*)src->"; S += (*I)->getNameAsString(); - if (BlockByRefDecls.count((*I))) + if (BlockByRefDeclsPtrSet.count((*I))) S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; else S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; @@ -3877,7 +3946,7 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, E = ImportedBlockDecls.end(); I != E; ++I) { S += "_Block_object_dispose((void*)src->"; S += (*I)->getNameAsString(); - if (BlockByRefDecls.count((*I))) + if (BlockByRefDeclsPtrSet.count((*I))) S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; else S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; @@ -3901,7 +3970,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, if (BlockDeclRefs.size()) { // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -3927,7 +3996,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, S += FieldName + ";\n"; } // Output all "by ref" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -3966,7 +4035,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, Constructor += " Desc = desc;\n"; // Initialize all "by copy" arguments. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -3977,7 +4046,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, Constructor += Name + ";\n"; } // Initialize all "by ref" arguments. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -4047,23 +4116,25 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); - InsertText(FunLocStart, CI.c_str(), CI.size()); + InsertText(FunLocStart, CI); std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); - InsertText(FunLocStart, CF.c_str(), CF.size()); + InsertText(FunLocStart, CF); if (ImportedBlockDecls.size()) { std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); - InsertText(FunLocStart, HF.c_str(), HF.size()); + InsertText(FunLocStart, HF); } std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, ImportedBlockDecls.size() > 0); - InsertText(FunLocStart, BD.c_str(), BD.size()); + InsertText(FunLocStart, BD); BlockDeclRefs.clear(); BlockByRefDecls.clear(); + BlockByRefDeclsPtrSet.clear(); BlockByCopyDecls.clear(); + BlockByCopyDeclsPtrSet.clear(); BlockCallExprs.clear(); ImportedBlockDecls.clear(); } @@ -4078,17 +4149,23 @@ void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { SynthesizeBlockLiterals(FunLocStart, FuncName); } -void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { - //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); - //SourceLocation FunLocStart = MD->getLocStart(); - // FIXME: This hack works around a bug in Rewrite.InsertText(). - SourceLocation FunLocStart = MD->getLocStart().getFileLocWithOffset(-1); - std::string FuncName = MD->getSelector().getAsString(); +static void BuildUniqueMethodName(std::string &Name, + ObjCMethodDecl *MD) { + ObjCInterfaceDecl *IFace = MD->getClassInterface(); + Name = IFace->getNameAsCString(); + Name += "__" + MD->getSelector().getAsString(); // Convert colons to underscores. std::string::size_type loc = 0; - while ((loc = FuncName.find(":", loc)) != std::string::npos) - FuncName.replace(loc, 1, "_"); + while ((loc = Name.find(":", loc)) != std::string::npos) + Name.replace(loc, 1, "_"); +} +void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { + //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); + //SourceLocation FunLocStart = MD->getLocStart(); + SourceLocation FunLocStart = MD->getLocStart(); + std::string FuncName; + BuildUniqueMethodName(FuncName, MD); SynthesizeBlockLiterals(FunLocStart, FuncName.c_str()); } @@ -4304,11 +4381,9 @@ void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { std::string TypeAsString = "("; TypeAsString += QT.getAsString(); TypeAsString += ")"; - ReplaceText(LocStart, endBuf-startBuf+1, - TypeAsString.c_str(), TypeAsString.size()); + ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); return; } - // advance the location to startArgList. const char *argPtr = startBuf; @@ -4317,7 +4392,7 @@ void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { case '^': // Replace the '^' with '*'. LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf); - ReplaceText(LocStart, 1, "*", 1); + ReplaceText(LocStart, 1, "*"); break; } } @@ -4346,7 +4421,7 @@ void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { case '^': // Replace the '^' with '*'. DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList); - ReplaceText(DeclLoc, 1, "*", 1); + ReplaceText(DeclLoc, 1, "*"); break; case '(': parenCount++; @@ -4427,7 +4502,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { if (*startBuf == '^') { // Replace the '^' with '*', computing a negative offset. DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf); - ReplaceText(DeclLoc, 1, "*", 1); + ReplaceText(DeclLoc, 1, "*"); } if (PointerTypeTakesAnyBlockArguments(DeclT)) { // Replace the '^' with '*' for arguments. @@ -4438,7 +4513,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { while (argListBegin < argListEnd) { if (*argListBegin == '^') { SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf); - ReplaceText(CaretLoc, 1, "*", 1); + ReplaceText(CaretLoc, 1, "*"); } argListBegin++; } @@ -4563,7 +4638,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); FunLocStart = CurMethodDef->getLocStart(); } - InsertText(FunLocStart, ByrefType.c_str(), ByrefType.size()); + InsertText(FunLocStart, ByrefType); if (Ty.isObjCGCWeak()) { flag |= BLOCK_FIELD_IS_WEAK; isa = 1; @@ -4579,7 +4654,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { flag |= BLOCK_FIELD_IS_OBJECT; std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); if (!HF.empty()) - InsertText(FunLocStart, HF.c_str(), HF.size()); + InsertText(FunLocStart, HF); } // struct __Block_byref_ND ND = @@ -4592,10 +4667,12 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { Name = ND->getNameAsString(); ByrefType.clear(); RewriteByRefString(ByrefType, Name, ND); + std::string ForwardingCastType("("); + ForwardingCastType += ByrefType + " *)"; if (!hasInit) { ByrefType += " " + Name + " = {(void*)"; ByrefType += utostr(isa); - ByrefType += ", &" + Name + ", "; + ByrefType += "," + ForwardingCastType + "&" + Name + ", "; ByrefType += utostr(flags); ByrefType += ", "; ByrefType += "sizeof("; @@ -4608,8 +4685,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += utostr(flag); } ByrefType += "};\n"; - ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), - ByrefType.c_str(), ByrefType.size()); + ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), ByrefType); } else { SourceLocation startLoc; @@ -4624,7 +4700,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += " " + Name; ByrefType += " = {(void*)"; ByrefType += utostr(isa); - ByrefType += ", &" + Name + ", "; + ByrefType += "," + ForwardingCastType + "&" + Name + ", "; ByrefType += utostr(flags); ByrefType += ", "; ByrefType += "sizeof("; @@ -4637,8 +4713,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += utostr(flag); ByrefType += ", "; } - ReplaceText(DeclLoc, endBuf-startBuf, - ByrefType.c_str(), ByrefType.size()); + ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); // Complete the newly synthesized compound expression by inserting a right // curly brace before the end of the declaration. @@ -4654,7 +4729,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf); - InsertText(semiLoc, "}", 1); + InsertText(semiLoc, "}"); } return; } @@ -4665,12 +4740,19 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { if (BlockDeclRefs.size()) { // Unique all "by copy" declarations. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) - if (!BlockDeclRefs[i]->isByRef()) - BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl()); + if (!BlockDeclRefs[i]->isByRef()) { + if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { + BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); + BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); + } + } // Unique all "by ref" declarations. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) if (BlockDeclRefs[i]->isByRef()) { - BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl()); + if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { + BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); + BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); + } } // Find any imported blocks...they will need special attention. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) @@ -4699,13 +4781,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { if (CurFunctionDef) FuncName = CurFunctionDef->getNameAsString(); - else if (CurMethodDef) { - FuncName = CurMethodDef->getSelector().getAsString(); - // Convert colons to underscores. - std::string::size_type loc = 0; - while ((loc = FuncName.find(":", loc)) != std::string::npos) - FuncName.replace(loc, 1, "_"); - } else if (GlobalVarDecl) + else if (CurMethodDef) + BuildUniqueMethodName(FuncName, CurMethodDef); + else if (GlobalVarDecl) FuncName = std::string(GlobalVarDecl->getNameAsString()); std::string BlockNumber = utostr(Blocks.size()-1); @@ -4752,7 +4830,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { if (BlockDeclRefs.size()) { Expr *Exp; // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { if (isObjCType((*I)->getType())) { // FIXME: Conform to ABI ([[obj retain] autorelease]). @@ -4770,13 +4848,25 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { InitExprs.push_back(Exp); } // Output all "by ref" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { + ValueDecl *ND = (*I); + std::string Name(ND->getNameAsString()); + std::string RecName; + RewriteByRefString(RecName, Name, ND); + IdentifierInfo *II = &Context->Idents.get(RecName.c_str() + + sizeof("struct")); + RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, + SourceLocation(), II); + assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); + QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); + FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, Context->getPointerType(Exp->getType()), SourceLocation()); + Exp = NoTypeInfoCStyleCastExpr(Context, castT, CastExpr::CK_Unknown, Exp); InitExprs.push_back(Exp); } } @@ -4798,7 +4888,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { NewRep); BlockDeclRefs.clear(); BlockByRefDecls.clear(); + BlockByRefDeclsPtrSet.clear(); BlockByCopyDecls.clear(); + BlockByCopyDeclsPtrSet.clear(); ImportedBlockDecls.clear(); return NewRep; } @@ -4843,7 +4935,21 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E; ++CI) if (*CI) { - Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(*CI); + Stmt *newStmt; + Stmt *S = (*CI); + if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { + Expr *OldBase = IvarRefExpr->getBase(); + bool replaced = false; + newStmt = RewriteObjCNestedIvarRefExpr(S, replaced); + if (replaced) { + if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt)) + ReplaceStmt(OldBase, IRE->getBase()); + else + ReplaceStmt(S, newStmt); + } + } + else + newStmt = RewriteFunctionBodyOrGlobalInitializer(S); if (newStmt) *CI = newStmt; } @@ -4865,9 +4971,6 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) return RewriteAtEncode(AtEncode); - if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) - return RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin()); - if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S)) { BinaryOperator *BinOp = PropSetters[PropRefExpr]; if (BinOp) { @@ -4995,7 +5098,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { RewriteBlockPointerDecl(ND); else if (ND->getType()->isFunctionPointerType()) CheckFunctionPointerDecl(ND->getType(), ND); - if (VarDecl *VD = dyn_cast<VarDecl>(SD)) + if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { if (VD->hasAttr<BlocksAttr>()) { static unsigned uniqueByrefDeclCount = 0; assert(!BlockByRefDeclNo.count(ND) && @@ -5003,6 +5106,9 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; RewriteByRefVar(VD); } + else + RewriteTypeOfDecl(VD); + } } if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) @@ -5191,11 +5297,6 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { } void RewriteObjC::HandleTranslationUnit(ASTContext &C) { - // Get the top-level buffer that this corresponds to. - - // Rewrite tabs if we care. - //RewriteTabs(); - if (Diags.hasErrorOccurred()) return; @@ -5207,8 +5308,7 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) { E = ProtocolExprDecls.end(); I != E; ++I) RewriteObjCProtocolMetaData(*I, "", "", Preamble); - InsertText(SM->getLocForStartOfFile(MainFileID), - Preamble.c_str(), Preamble.size(), false); + InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); if (ClassImplementation.size() || CategoryImplementation.size()) RewriteImplementations(); @@ -5219,7 +5319,7 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) { //printf("Changed:\n"); *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); } else { - fprintf(stderr, "No changes\n"); + llvm::errs() << "No changes\n"; } if (ClassImplementation.size() || CategoryImplementation.size() || diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 83b4542..9ec5ffe 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -104,11 +104,6 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, if (StartColNo) --StartColNo; // Zero base the col #. } - // Pick the first non-whitespace column. - while (StartColNo < SourceLine.size() && - (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t')) - ++StartColNo; - // Compute the column number of the end. unsigned EndColNo = CaretLine.size(); if (EndLineNo == LineNo) { @@ -123,16 +118,25 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, } } + assert(StartColNo <= EndColNo && "Invalid range!"); + + // Pick the first non-whitespace column. + while (StartColNo < SourceLine.size() && + (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t')) + ++StartColNo; + // Pick the last non-whitespace column. - if (EndColNo <= SourceLine.size()) - while (EndColNo-1 && - (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t')) - --EndColNo; - else + if (EndColNo > SourceLine.size()) EndColNo = SourceLine.size(); + while (EndColNo-1 && + (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t')) + --EndColNo; + + // If the start/end passed each other, then we are trying to highlight a range + // that just exists in whitespace, which must be some sort of other bug. + assert(StartColNo <= EndColNo && "Trying to highlight whitespace??"); // Fill the range with ~'s. - assert(StartColNo <= EndColNo && "Invalid range!"); for (unsigned i = StartColNo; i < EndColNo; ++i) CaretLine[i] = '~'; } |