diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
commit | 4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch) | |
tree | 137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Frontend | |
parent | 5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff) | |
download | src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip |
Update clang to r84119.vendor/clang/clang-r84119
Notes
Notes:
svn path=/vendor/clang/dist/; revision=198092
svn path=/vendor/clang/clang-84119/; revision=198093; tag=vendor/clang/clang-r84119
Diffstat (limited to 'lib/Frontend')
34 files changed, 3710 insertions, 2765 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 8f0ad13319eb..8d76680f6f92 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/ASTConsumers.h" -#include "clang/Frontend/DocumentXML.h" +#include "clang/Frontend/DocumentXML.h" #include "clang/Frontend/PathDiagnosticClients.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" @@ -20,13 +20,16 @@ #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/PrettyPrinter.h" #include "clang/CodeGen/ModuleBuilder.h" #include "llvm/Module.h" -#include "llvm/Support/Streams.h" +#include "llvm/Support/Format.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" +#include <cstdio> + using namespace clang; //===----------------------------------------------------------------------===// @@ -36,11 +39,11 @@ namespace { class ASTPrinter : public ASTConsumer { llvm::raw_ostream &Out; bool Dump; - + public: - ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false) + ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false) : Out(o? *o : llvm::errs()), Dump(Dump) { } - + virtual void HandleTranslationUnit(ASTContext &Context) { PrintingPolicy Policy = Context.PrintingPolicy; Policy.Dump = Dump; @@ -62,21 +65,19 @@ namespace { public: ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {} - + void Initialize(ASTContext &Context) { Doc.initialize(Context); } virtual void HandleTranslationUnit(ASTContext &Ctx) { Doc.addSubNode("TranslationUnit"); - for (DeclContext::decl_iterator + for (DeclContext::decl_iterator D = Ctx.getTranslationUnitDecl()->decls_begin(), DEnd = Ctx.getTranslationUnitDecl()->decls_end(); - D != DEnd; + D != DEnd; ++D) - { Doc.PrintDecl(*D); - } Doc.toParent(); Doc.finalize(); } @@ -87,9 +88,9 @@ namespace { ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) { return new ASTPrinterXML(out ? *out : llvm::outs()); } - -ASTConsumer *clang::CreateASTDumper() { - return new ASTPrinter(0, true); + +ASTConsumer *clang::CreateASTDumper() { + return new ASTPrinter(0, true); } //===----------------------------------------------------------------------===// @@ -107,7 +108,7 @@ namespace { for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) HandleTopLevelSingleDecl(*I); } - + void HandleTopLevelSingleDecl(Decl *D); }; } @@ -115,22 +116,22 @@ namespace { void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { FD->print(llvm::errs()); - - if (FD->getBodyIfAvailable()) { - llvm::cerr << '\n'; - FD->getBodyIfAvailable()->viewAST(); - llvm::cerr << '\n'; + + if (Stmt *Body = FD->getBody()) { + llvm::errs() << '\n'; + Body->viewAST(); + llvm::errs() << '\n'; } return; } - + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { MD->print(llvm::errs()); - + if (MD->getBody()) { - llvm::cerr << '\n'; + llvm::errs() << '\n'; MD->getBody()->viewAST(); - llvm::cerr << '\n'; + llvm::errs() << '\n'; } } } @@ -156,7 +157,7 @@ public: }; } // end anonymous namespace -void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, +void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, unsigned Indentation) { // Print DeclContext name. switch (DC->getDeclKind()) { @@ -230,7 +231,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, // Print the parameters. Out << "("; bool PrintComma = false; - for (FunctionDecl::param_const_iterator I = FD->param_begin(), + for (FunctionDecl::param_const_iterator I = FD->param_begin(), E = FD->param_end(); I != E; ++I) { if (PrintComma) Out << ", "; @@ -253,7 +254,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, // Print the parameters. Out << "("; bool PrintComma = false; - for (FunctionDecl::param_const_iterator I = D->param_begin(), + for (FunctionDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) { if (PrintComma) Out << ", "; @@ -283,7 +284,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, // Print the parameters. Out << "("; bool PrintComma = false; - for (FunctionDecl::param_const_iterator I = D->param_begin(), + for (FunctionDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) { if (PrintComma) Out << ", "; @@ -353,7 +354,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, case Decl::CXXRecord: case Decl::ObjCMethod: case Decl::ObjCInterface: - case Decl::ObjCCategory: + case Decl::ObjCCategory: case Decl::ObjCProtocol: case Decl::ObjCImplementation: case Decl::ObjCCategoryImpl: @@ -415,8 +416,150 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, } } } -ASTConsumer *clang::CreateDeclContextPrinter() { - return new DeclContextPrinter(); +ASTConsumer *clang::CreateDeclContextPrinter() { + return new DeclContextPrinter(); +} + +//===----------------------------------------------------------------------===// +/// RecordLayoutDumper - C++ Record Layout Dumping. +namespace { +class RecordLayoutDumper : public ASTConsumer { + llvm::raw_ostream& Out; + + void PrintOffset(uint64_t Offset, unsigned IndentLevel) { + Out << llvm::format("%4d | ", Offset); + for (unsigned I = 0; I < IndentLevel * 2; ++I) Out << ' '; + } + + void DumpRecordLayoutOffsets(const CXXRecordDecl *RD, ASTContext &C, + uint64_t Offset, + unsigned IndentLevel, const char* Description, + bool IncludeVirtualBases) { + const ASTRecordLayout &Info = C.getASTRecordLayout(RD); + + PrintOffset(Offset, IndentLevel); + Out << C.getTypeDeclType((CXXRecordDecl *)RD).getAsString(); + if (Description) + Out << ' ' << Description; + if (RD->isEmpty()) + Out << " (empty)"; + Out << '\n'; + + IndentLevel++; + + const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase(); + + // Vtable pointer. + if (RD->isDynamicClass() && !PrimaryBase) { + PrintOffset(Offset, IndentLevel); + Out << '(' << RD->getNameAsString() << " vtable pointer)\n"; + } + // Dump (non-virtual) bases + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + if (I->isVirtual()) + continue; + + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8; + + DumpRecordLayoutOffsets(Base, C, BaseOffset, IndentLevel, + Base == PrimaryBase ? "(primary base)" : "(base)", + /*IncludeVirtualBases=*/false); + } + + // Dump fields. + uint64_t FieldNo = 0; + for (CXXRecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); I != E; ++I, ++FieldNo) { + const FieldDecl *Field = *I; + uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8; + + if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { + if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + DumpRecordLayoutOffsets(D, C, FieldOffset, IndentLevel, + Field->getNameAsCString(), + /*IncludeVirtualBases=*/true); + continue; + } + } + + PrintOffset(FieldOffset, IndentLevel); + Out << Field->getType().getAsString() << ' '; + Out << Field->getNameAsString() << '\n'; + } + + if (!IncludeVirtualBases) + return; + + // Dump virtual bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), + E = RD->vbases_end(); I != E; ++I) { + assert(I->isVirtual() && "Found non-virtual class!"); + const CXXRecordDecl *VBase = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8; + DumpRecordLayoutOffsets(VBase, C, VBaseOffset, IndentLevel, + VBase == PrimaryBase ? + "(primary virtual base)" : "(virtual base)", + /*IncludeVirtualBases=*/false); + } + } + + // FIXME: Maybe this could be useful in ASTContext.cpp. + void DumpRecordLayout(const CXXRecordDecl *RD, ASTContext &C) { + const ASTRecordLayout &Info = C.getASTRecordLayout(RD); + + DumpRecordLayoutOffsets(RD, C, 0, 0, 0, + /*IncludeVirtualBases=*/true); + Out << " sizeof=" << Info.getSize() / 8; + Out << ", dsize=" << Info.getDataSize() / 8; + Out << ", align=" << Info.getAlignment() / 8 << '\n'; + Out << " nvsize=" << Info.getNonVirtualSize() / 8; + Out << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n'; + Out << '\n'; + } + +public: + RecordLayoutDumper() : Out(llvm::errs()) {} + + void HandleTranslationUnit(ASTContext &C) { + for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end(); + I != E; ++I) { + const RecordType *RT = dyn_cast<RecordType>(*I); + if (!RT) + continue; + + const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); + if (!RD) + continue; + + if (RD->isImplicit()) + continue; + + if (RD->isDependentType()) + continue; + + if (RD->isInvalidDecl()) + continue; + + if (!RD->getDefinition(C)) + continue; + + // FIXME: Do we really need to hard code this? + if (RD->getQualifiedNameAsString() == "__va_list_tag") + continue; + + DumpRecordLayout(RD, C); + } + } +}; +} // end anonymous namespace +ASTConsumer *clang::CreateRecordLayoutDumper() { + return new RecordLayoutDumper(); } //===----------------------------------------------------------------------===// @@ -427,7 +570,7 @@ class InheritanceViewer : public ASTConsumer { const std::string clsname; public: InheritanceViewer(const std::string& cname) : clsname(cname) {} - + void HandleTranslationUnit(ASTContext &C) { for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I) if (RecordType *T = dyn_cast<RecordType>(*I)) { @@ -435,12 +578,12 @@ public: // FIXME: This lookup needs to be generalized to handle namespaces and // (when we support them) templates. if (D->getNameAsString() == clsname) { - D->viewInheritance(C); + D->viewInheritance(C); } } } } -}; +}; } ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) { diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 8143263ca2f9..d3475b5236d9 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -13,7 +13,6 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/PCHReader.h" -#include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" @@ -25,7 +24,7 @@ using namespace clang; -ASTUnit::ASTUnit() { } +ASTUnit::ASTUnit(Diagnostic &_Diags) : Diags(_Diags) { } ASTUnit::~ASTUnit() { } namespace { @@ -38,38 +37,38 @@ class VISIBILITY_HIDDEN PCHInfoCollector : public PCHReaderListener { std::string &TargetTriple; std::string &Predefines; unsigned &Counter; - + unsigned NumHeaderInfos; - + public: PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI, std::string &TargetTriple, std::string &Predefines, unsigned &Counter) : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple), Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {} - + virtual bool ReadLanguageOptions(const LangOptions &LangOpts) { LangOpt = LangOpts; return false; } - + virtual bool ReadTargetTriple(const std::string &Triple) { TargetTriple = Triple; return false; } - - virtual bool ReadPredefinesBuffer(const char *PCHPredef, + + virtual bool ReadPredefinesBuffer(const char *PCHPredef, unsigned PCHPredefLen, FileID PCHBufferID, std::string &SuggestedPredefines) { Predefines = PCHPredef; return false; } - + virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI) { HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++); } - + virtual void ReadCounter(unsigned Value) { Counter = Value; } @@ -77,24 +76,24 @@ public: } // anonymous namespace +const std::string &ASTUnit::getOriginalSourceFileName() { + return dyn_cast<PCHReader>(Ctx->getExternalSource())->getOriginalSourceFile(); +} + +FileManager &ASTUnit::getFileManager() { + return HeaderInfo->getFileMgr(); +} ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, + Diagnostic &Diags, FileManager &FileMgr, std::string *ErrMsg) { - - llvm::OwningPtr<ASTUnit> AST(new ASTUnit()); - - AST->DiagClient.reset(new TextDiagnosticBuffer()); - AST->Diags.reset(new Diagnostic(AST->DiagClient.get())); + llvm::OwningPtr<ASTUnit> AST(new ASTUnit(Diags)); AST->HeaderInfo.reset(new HeaderSearch(FileMgr)); - AST->SourceMgr.reset(new SourceManager()); - - Diagnostic &Diags = *AST->Diags.get(); - SourceManager &SourceMgr = *AST->SourceMgr.get(); // Gather Info for preprocessor construction later on. - + LangOptions LangInfo; HeaderSearch &HeaderInfo = *AST->HeaderInfo.get(); std::string TargetTriple; @@ -104,37 +103,37 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, llvm::OwningPtr<PCHReader> Reader; llvm::OwningPtr<ExternalASTSource> Source; - Reader.reset(new PCHReader(SourceMgr, FileMgr, Diags)); + Reader.reset(new PCHReader(AST->getSourceManager(), FileMgr, AST->Diags)); Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple, Predefines, Counter)); switch (Reader->ReadPCH(Filename)) { case PCHReader::Success: break; - + case PCHReader::Failure: case PCHReader::IgnorePCH: if (ErrMsg) *ErrMsg = "Could not load PCH file"; return NULL; } - + // PCH loaded successfully. Now create the preprocessor. - + // Get information about the target being compiled for. AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple)); - AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(), - SourceMgr, HeaderInfo)); + AST->PP.reset(new Preprocessor(AST->Diags, LangInfo, *AST->Target.get(), + AST->getSourceManager(), HeaderInfo)); Preprocessor &PP = *AST->PP.get(); - PP.setPredefines(Predefines); + PP.setPredefines(Reader->getSuggestedPredefines()); PP.setCounterValue(Counter); Reader->setPreprocessor(PP); - + // Create and initialize the ASTContext. AST->Ctx.reset(new ASTContext(LangInfo, - SourceMgr, + AST->getSourceManager(), *AST->Target.get(), PP.getIdentifierTable(), PP.getSelectorTable(), @@ -142,14 +141,14 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, /* FreeMemory = */ true, /* size_reserve = */0)); ASTContext &Context = *AST->Ctx.get(); - + Reader->InitializeContext(Context); - + // Attach the PCH reader to the AST context as an external AST // source, so that declarations will be deserialized from the // PCH file as needed. Source.reset(Reader.take()); Context.setExternalSource(Source); - return AST.take(); + return AST.take(); } diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index 06af2d9a4e58..276599470b78 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -17,39 +17,51 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" -#include "llvm/Support/Compiler.h" -#include "llvm/ADT/OwningPtr.h" -#include "clang/AST/CFG.h" +#include "clang/Analysis/CFG.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/AST/ParentMap.h" +#include "clang/Analysis/PathSensitive/AnalysisManager.h" #include "clang/Analysis/PathSensitive/BugReporter.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/LocalCheckers.h" #include "clang/Analysis/PathSensitive/GRTransferFuncs.h" #include "clang/Analysis/PathSensitive/GRExprEngine.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Streams.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" #include "llvm/System/Program.h" +#include "llvm/ADT/OwningPtr.h" using namespace clang; -static ExplodedNodeImpl::Auditor* CreateUbiViz(); +static ExplodedNode::Auditor* CreateUbiViz(); //===----------------------------------------------------------------------===// // Basic type definitions. //===----------------------------------------------------------------------===// -namespace { - class AnalysisManager; - typedef void (*CodeAction)(AnalysisManager& Mgr); +namespace { + typedef void (*CodeAction)(AnalysisManager& Mgr, Decl *D); } // end anonymous namespace //===----------------------------------------------------------------------===// +// Special PathDiagnosticClients. +//===----------------------------------------------------------------------===// + +static PathDiagnosticClient* +CreatePlistHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP, + PreprocessorFactory* PPF) { + llvm::sys::Path F(prefix); + PathDiagnosticClientFactory *PF = + CreateHTMLDiagnosticClientFactory(F.getDirname(), PP, PPF); + return CreatePlistDiagnosticClient(prefix, PP, PPF, PF); +} + +//===----------------------------------------------------------------------===// // AnalysisConsumer declaration. //===----------------------------------------------------------------------===// @@ -61,16 +73,24 @@ namespace { Actions ObjCMethodActions; Actions ObjCImplementationActions; Actions TranslationUnitActions; - + public: - const LangOptions& LOpts; + const LangOptions& LOpts; Diagnostic &Diags; ASTContext* Ctx; Preprocessor* PP; PreprocessorFactory* PPF; const std::string OutDir; AnalyzerOptions Opts; - llvm::OwningPtr<PathDiagnosticClient> PD; + + + // PD is owned by AnalysisManager. + PathDiagnosticClient *PD; + + StoreManagerCreator CreateStoreMgr; + ConstraintManagerCreator CreateConstraintMgr; + + llvm::OwningPtr<AnalysisManager> Mgr; AnalysisConsumer(Diagnostic &diags, Preprocessor* pp, PreprocessorFactory* ppf, @@ -79,181 +99,30 @@ namespace { const AnalyzerOptions& opts) : LOpts(lopts), Diags(diags), Ctx(0), PP(pp), PPF(ppf), - OutDir(outdir), Opts(opts) {} - - void addCodeAction(CodeAction action) { - FunctionActions.push_back(action); - ObjCMethodActions.push_back(action); - } - - void addObjCImplementationAction(CodeAction action) { - ObjCImplementationActions.push_back(action); - } - - void addTranslationUnitAction(CodeAction action) { - TranslationUnitActions.push_back(action); - } - - virtual void Initialize(ASTContext &Context) { - Ctx = &Context; + OutDir(outdir), Opts(opts), PD(0) { + DigestAnalyzerOptions(); } - - virtual void HandleTopLevelDecl(DeclGroupRef D) { - for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) - HandleTopLevelSingleDecl(*I); - } - - void HandleTopLevelSingleDecl(Decl *D); - virtual void HandleTranslationUnit(ASTContext &C); - - void HandleCode(Decl* D, Stmt* Body, Actions& actions); - }; - - - class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData { - Decl* D; Stmt* Body; - - enum AnalysisScope { ScopeTU, ScopeDecl } AScope; - - AnalysisConsumer& C; - bool DisplayedFunction; - - llvm::OwningPtr<CFG> cfg; - llvm::OwningPtr<LiveVariables> liveness; - llvm::OwningPtr<ParentMap> PM; - - // Configurable components creators. - StoreManagerCreator CreateStoreMgr; - ConstraintManagerCreator CreateConstraintMgr; - public: - AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b, bool displayProgress) - : D(d), Body(b), AScope(ScopeDecl), C(c), - DisplayedFunction(!displayProgress) { - setManagerCreators(); - } - - AnalysisManager(AnalysisConsumer& c, bool displayProgress) - : D(0), Body(0), AScope(ScopeTU), C(c), - DisplayedFunction(!displayProgress) { - setManagerCreators(); - } - - Decl* getCodeDecl() const { - assert (AScope == ScopeDecl); - return D; - } - - Stmt* getBody() const { - assert (AScope == ScopeDecl); - return Body; - } - - StoreManagerCreator getStoreManagerCreator() { - return CreateStoreMgr; - }; - - ConstraintManagerCreator getConstraintManagerCreator() { - return CreateConstraintMgr; - } - - virtual CFG* getCFG() { - if (!cfg) cfg.reset(CFG::buildCFG(getBody())); - return cfg.get(); - } - - virtual ParentMap& getParentMap() { - if (!PM) - PM.reset(new ParentMap(getBody())); - return *PM.get(); - } - - virtual ASTContext& getContext() { - return *C.Ctx; - } - - virtual SourceManager& getSourceManager() { - return getContext().getSourceManager(); - } - - virtual Diagnostic& getDiagnostic() { - return C.Diags; - } - - const LangOptions& getLangOptions() const { - return C.LOpts; - } - - virtual PathDiagnosticClient* getPathDiagnosticClient() { - if (C.PD.get() == 0 && !C.OutDir.empty()) { - switch (C.Opts.AnalysisDiagOpt) { - default: -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\ -case PD_##NAME: C.PD.reset(CREATEFN(C.OutDir, C.PP, C.PPF)); break; + void DigestAnalyzerOptions() { + // Create the PathDiagnosticClient. + if (!OutDir.empty()) { + switch (Opts.AnalysisDiagOpt) { + default: +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \ + case PD_##NAME: PD = CREATEFN(OutDir, PP, PPF); break; #include "clang/Frontend/Analyses.def" } } - return C.PD.get(); - } - - virtual LiveVariables* getLiveVariables() { - if (!liveness) { - CFG* c = getCFG(); - if (!c) return 0; - - liveness.reset(new LiveVariables(getContext(), *c)); - liveness->runOnCFG(*c); - liveness->runOnAllBlocks(*c, 0, true); - } - - return liveness.get(); - } - - bool shouldVisualizeGraphviz() const { return C.Opts.VisualizeEGDot; } - bool shouldVisualizeUbigraph() const { return C.Opts.VisualizeEGUbi; } - - bool shouldVisualize() const { - return C.Opts.VisualizeEGDot || C.Opts.VisualizeEGUbi; - } - - bool shouldTrimGraph() const { return C.Opts.TrimGraph; } - - bool shouldPurgeDead() const { return C.Opts.PurgeDead; } - - bool shouldEagerlyAssume() const { return C.Opts.EagerlyAssume; } - - void DisplayFunction() { - - if (DisplayedFunction) - return; - - DisplayedFunction = true; - - // FIXME: Is getCodeDecl() always a named decl? - if (isa<FunctionDecl>(getCodeDecl()) || - isa<ObjCMethodDecl>(getCodeDecl())) { - NamedDecl *ND = cast<NamedDecl>(getCodeDecl()); - SourceManager &SM = getContext().getSourceManager(); - llvm::cerr << "ANALYZE: " - << SM.getPresumedLoc(ND->getLocation()).getFilename() - << ' ' << ND->getNameAsString() << '\n'; - } - } - - private: - /// Set configurable analyzer components creators. First check if there are - /// components registered at runtime. Otherwise fall back to builtin - /// components. - void setManagerCreators() { + // Create the analyzer component creators. if (ManagerRegistry::StoreMgrCreator != 0) { CreateStoreMgr = ManagerRegistry::StoreMgrCreator; } else { - switch (C.Opts.AnalysisStoreOpt) { + switch (Opts.AnalysisStoreOpt) { default: assert(0 && "Unknown store manager."); -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ case NAME##Model: CreateStoreMgr = CREATEFN; break; #include "clang/Frontend/Analyses.def" } @@ -262,7 +131,7 @@ case PD_##NAME: C.PD.reset(CREATEFN(C.OutDir, C.PP, C.PPF)); break; if (ManagerRegistry::ConstraintMgrCreator != 0) CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator; else { - switch (C.Opts.AnalysisConstraintsOpt) { + switch (Opts.AnalysisConstraintsOpt) { default: assert(0 && "Unknown store manager."); #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ @@ -270,20 +139,44 @@ case PD_##NAME: C.PD.reset(CREATEFN(C.OutDir, C.PP, C.PPF)); break; #include "clang/Frontend/Analyses.def" } } + } - - // Some DiagnosticClients should be created all the time instead of - // lazily. Create those now. - switch (C.Opts.AnalysisDiagOpt) { - default: break; -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\ -case PD_##NAME: if (AUTOCREATE) getPathDiagnosticClient(); break; -#include "clang/Frontend/Analyses.def" - } + void addCodeAction(CodeAction action) { + FunctionActions.push_back(action); + ObjCMethodActions.push_back(action); } + void addObjCImplementationAction(CodeAction action) { + ObjCImplementationActions.push_back(action); + } + + void addTranslationUnitAction(CodeAction action) { + TranslationUnitActions.push_back(action); + } + + virtual void Initialize(ASTContext &Context) { + Ctx = &Context; + Mgr.reset(new AnalysisManager(*Ctx, Diags, LOpts, PD, + CreateStoreMgr, CreateConstraintMgr, + Opts.AnalyzerDisplayProgress, + Opts.VisualizeEGDot, Opts.VisualizeEGUbi, + Opts.PurgeDead, Opts.EagerlyAssume, + Opts.TrimGraph)); + } + + virtual void HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) + HandleTopLevelSingleDecl(*I); + } + + void HandleTopLevelSingleDecl(Decl *D); + virtual void HandleTranslationUnit(ASTContext &C); + + void HandleCode(Decl* D, Stmt* Body, Actions& actions); }; + + } // end anonymous namespace namespace llvm { @@ -291,71 +184,85 @@ namespace llvm { static inline void Profile(CodeAction X, FoldingSetNodeID& ID) { ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X))); } - }; + }; } //===----------------------------------------------------------------------===// // AnalysisConsumer implementation. //===----------------------------------------------------------------------===// -void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { +void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { switch (D->getKind()) { case Decl::Function: { FunctionDecl* FD = cast<FunctionDecl>(D); - if (Opts.AnalyzeSpecificFunction.size() > 0 && + if (Opts.AnalyzeSpecificFunction.size() > 0 && Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName()) break; - + Stmt* Body = FD->getBody(); if (Body) HandleCode(FD, Body, FunctionActions); break; } - + case Decl::ObjCMethod: { ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); - + if (Opts.AnalyzeSpecificFunction.size() > 0 && Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString()) return; - + Stmt* Body = MD->getBody(); if (Body) HandleCode(MD, Body, ObjCMethodActions); break; } - + default: break; } } void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { + + TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + + if (!TranslationUnitActions.empty()) { + // Find the entry function definition (if any). + FunctionDecl *FD = 0; + + 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(!TranslationUnitActions.empty()) { - AnalysisManager mgr(*this, Opts.AnalyzerDisplayProgress); for (Actions::iterator I = TranslationUnitActions.begin(), E = TranslationUnitActions.end(); I != E; ++I) - (*I)(mgr); + (*I)(*Mgr, FD); } if (!ObjCImplementationActions.empty()) { - TranslationUnitDecl *TUD = C.getTranslationUnitDecl(); - - for (DeclContext::decl_iterator I = TUD->decls_begin(), - E = TUD->decls_end(); + for (DeclContext::decl_iterator I = TU->decls_begin(), + E = TU->decls_end(); I != E; ++I) if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I)) HandleCode(ID, 0, ObjCImplementationActions); } - - // Delete the PathDiagnosticClient here just in case the AnalysisConsumer - // object doesn't get released. This will cause any side-effects in the - // destructor of the PathDiagnosticClient to get executed. - PD.reset(); + + // Explicitly destroy the PathDiagnosticClient. This will flush its output. + // FIXME: This should be replaced with something that doesn't rely on + // side-effects in PathDiagnosticClient's destructor. + Mgr.reset(NULL); } -void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions& actions) { - +void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) { + // Don't run the actions if an error has occured with parsing the file. if (Diags.hasErrorOccurred()) return; @@ -364,154 +271,170 @@ void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions& actions) { // otherwise specified. if (!Opts.AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(D->getLocation())) - return; + return; - // Create an AnalysisManager that will manage the state for analyzing - // this method/function. - AnalysisManager mgr(*this, D, Body, Opts.AnalyzerDisplayProgress); - - // Dispatch on the actions. + // Dispatch on the actions. for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I) - (*I)(mgr); + (*I)(*Mgr, D); } //===----------------------------------------------------------------------===// // Analyses //===----------------------------------------------------------------------===// -static void ActionWarnDeadStores(AnalysisManager& mgr) { - if (LiveVariables* L = mgr.getLiveVariables()) { +static void ActionWarnDeadStores(AnalysisManager& mgr, Decl *D) { + if (LiveVariables *L = mgr.getLiveVariables(D)) { BugReporter BR(mgr); - CheckDeadStores(*L, BR); + CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR); } } -static void ActionWarnUninitVals(AnalysisManager& mgr) { - if (CFG* c = mgr.getCFG()) - CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic()); +static void ActionWarnUninitVals(AnalysisManager& mgr, Decl *D) { + if (CFG* c = mgr.getCFG(D)) + CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic()); } -static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf, - bool StandardWarnings = true) { - - +static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D, + GRTransferFuncs* tf) { + + llvm::OwningPtr<GRTransferFuncs> TF(tf); // Display progress. - mgr.DisplayFunction(); - - // Construct the analysis engine. - LiveVariables* L = mgr.getLiveVariables(); - if (!L) return; + mgr.DisplayFunction(D); - GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L, mgr, - mgr.shouldPurgeDead(), mgr.shouldEagerlyAssume(), - mgr.getStoreManagerCreator(), - mgr.getConstraintManagerCreator()); + // Construct the analysis engine. We first query for the LiveVariables + // information to see if the CFG is valid. + // FIXME: Inter-procedural analysis will need to handle invalid CFGs. + if (!mgr.getLiveVariables(D)) + return; + + GRExprEngine Eng(mgr); Eng.setTransferFunctions(tf); - - if (StandardWarnings) { - Eng.RegisterInternalChecks(); - RegisterAppleChecks(Eng); - } + Eng.RegisterInternalChecks(); // FIXME: Internal checks should just + // automatically register. + RegisterAppleChecks(Eng, *D); + // Set the graph auditor. - llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor; + llvm::OwningPtr<ExplodedNode::Auditor> Auditor; if (mgr.shouldVisualizeUbigraph()) { Auditor.reset(CreateUbiViz()); - ExplodedNodeImpl::SetAuditor(Auditor.get()); + ExplodedNode::SetAuditor(Auditor.get()); } - + // Execute the worklist algorithm. - Eng.ExecuteWorkList(); - + Eng.ExecuteWorkList(mgr.getStackFrame(D)); + // Release the auditor (if any) so that it doesn't monitor the graph // created BugReporter. - ExplodedNodeImpl::SetAuditor(0); + ExplodedNode::SetAuditor(0); // Visualize the exploded graph. if (mgr.shouldVisualizeGraphviz()) Eng.ViewGraph(mgr.shouldTrimGraph()); - + // Display warnings. Eng.getBugReporter().FlushReports(); } -static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled, - bool StandardWarnings) { - - GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(), +static void ActionCheckerCFRefAux(AnalysisManager& mgr, Decl *D, + bool GCEnabled) { + + GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(), GCEnabled, mgr.getLangOptions()); - - ActionGRExprEngine(mgr, TF, StandardWarnings); + + ActionGRExprEngine(mgr, D, TF); } -static void ActionCheckerCFRef(AnalysisManager& mgr) { - +static void ActionCheckerCFRef(AnalysisManager& mgr, Decl *D) { + switch (mgr.getLangOptions().getGCMode()) { default: assert (false && "Invalid GC mode."); case LangOptions::NonGC: - ActionCheckerCFRefAux(mgr, false, true); + ActionCheckerCFRefAux(mgr, D, false); break; - + case LangOptions::GCOnly: - ActionCheckerCFRefAux(mgr, true, true); + ActionCheckerCFRefAux(mgr, D, true); break; - + case LangOptions::HybridGC: - ActionCheckerCFRefAux(mgr, false, true); - ActionCheckerCFRefAux(mgr, true, false); + ActionCheckerCFRefAux(mgr, D, false); + ActionCheckerCFRefAux(mgr, D, true); break; } } -static void ActionDisplayLiveVariables(AnalysisManager& mgr) { - if (LiveVariables* L = mgr.getLiveVariables()) { - mgr.DisplayFunction(); +static void ActionDisplayLiveVariables(AnalysisManager& mgr, Decl *D) { + if (LiveVariables* L = mgr.getLiveVariables(D)) { + mgr.DisplayFunction(D); L->dumpBlockLiveness(mgr.getSourceManager()); } } -static void ActionCFGDump(AnalysisManager& mgr) { - if (CFG* c = mgr.getCFG()) { - mgr.DisplayFunction(); - LangOptions LO; // FIXME! - c->dump(LO); +static void ActionCFGDump(AnalysisManager& mgr, Decl *D) { + if (CFG* c = mgr.getCFG(D)) { + mgr.DisplayFunction(D); + c->dump(mgr.getLangOptions()); } } -static void ActionCFGView(AnalysisManager& mgr) { - if (CFG* c = mgr.getCFG()) { - mgr.DisplayFunction(); - LangOptions LO; // FIXME! - c->viewCFG(LO); +static void ActionCFGView(AnalysisManager& mgr, Decl *D) { + if (CFG* c = mgr.getCFG(D)) { + mgr.DisplayFunction(D); + c->viewCFG(mgr.getLangOptions()); } } -static void ActionWarnObjCDealloc(AnalysisManager& mgr) { +static void ActionSecuritySyntacticChecks(AnalysisManager &mgr, Decl *D) { + BugReporter BR(mgr); + CheckSecuritySyntaxOnly(D, BR); +} + +static void ActionWarnObjCDealloc(AnalysisManager& mgr, Decl *D) { if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly) return; - + BugReporter BR(mgr); - - CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), - mgr.getLangOptions(), BR); + CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR); } -static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) { +static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr, Decl *D) { BugReporter BR(mgr); - CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR); + CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR); } -static void ActionWarnObjCMethSigs(AnalysisManager& mgr) { +static void ActionWarnObjCMethSigs(AnalysisManager& mgr, Decl *D) { BugReporter BR(mgr); + + CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR); +} + +static void ActionInlineCall(AnalysisManager &mgr, Decl *D) { + if (!D) + return; + + llvm::OwningPtr<GRTransferFuncs> TF(CreateCallInliner(mgr.getASTContext())); + + // Construct the analysis engine. + GRExprEngine Eng(mgr); + + Eng.setTransferFunctions(TF.get()); - CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), - BR); + Eng.RegisterInternalChecks(); + RegisterAppleChecks(Eng, *D); + + // Execute the worklist algorithm. + Eng.ExecuteWorkList(mgr.getStackFrame(D)); + + // Visualize the exploded graph. + if (mgr.shouldVisualizeGraphviz()) + Eng.ViewGraph(mgr.shouldTrimGraph()); } //===----------------------------------------------------------------------===// @@ -537,7 +460,7 @@ ASTConsumer* clang::CreateAnalysisConsumer(Diagnostic &diags, Preprocessor* pp, #include "clang/Frontend/Analyses.def" default: break; } - + // Last, disable the effects of '-Werror' when using the AnalysisConsumer. diags.setWarningsAsErrors(false); @@ -549,29 +472,29 @@ ASTConsumer* clang::CreateAnalysisConsumer(Diagnostic &diags, Preprocessor* pp, //===----------------------------------------------------------------------===// namespace { - -class UbigraphViz : public ExplodedNodeImpl::Auditor { + +class UbigraphViz : public ExplodedNode::Auditor { llvm::OwningPtr<llvm::raw_ostream> Out; llvm::sys::Path Dir, Filename; unsigned Cntr; typedef llvm::DenseMap<void*,unsigned> VMap; VMap M; - + public: UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir, llvm::sys::Path& filename); - + ~UbigraphViz(); - - virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst); + + virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst); }; - + } // end anonymous namespace -static ExplodedNodeImpl::Auditor* CreateUbiViz() { +static ExplodedNode::Auditor* CreateUbiViz() { std::string ErrMsg; - + llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); if (!ErrMsg.empty()) return 0; @@ -583,33 +506,32 @@ static ExplodedNodeImpl::Auditor* CreateUbiViz() { if (!ErrMsg.empty()) return 0; - llvm::cerr << "Writing '" << Filename << "'.\n"; - + llvm::errs() << "Writing '" << Filename.str() << "'.\n"; + llvm::OwningPtr<llvm::raw_fd_ostream> Stream; - std::string filename = Filename.toString(); - Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), false, ErrMsg)); + Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg)); if (!ErrMsg.empty()) return 0; - + return new UbigraphViz(Stream.take(), Dir, Filename); } -void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) { - +void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) { + assert (Src != Dst && "Self-edges are not allowed."); - + // Lookup the Src. If it is a new node, it's a root. VMap::iterator SrcI= M.find(Src); unsigned SrcID; - + if (SrcI == M.end()) { M[Src] = SrcID = Cntr++; *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n"; } else SrcID = SrcI->second; - + // Lookup the Dst. VMap::iterator DstI= M.find(Dst); unsigned DstID; @@ -625,7 +547,7 @@ void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) { } // Add the edge. - *Out << "('edge', " << SrcID << ", " << DstID + *Out << "('edge', " << SrcID << ", " << DstID << ", ('arrow','true'), ('oriented', 'true'))\n"; } @@ -640,18 +562,18 @@ UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir, UbigraphViz::~UbigraphViz() { Out.reset(0); - llvm::cerr << "Running 'ubiviz' program... "; + llvm::errs() << "Running 'ubiviz' program... "; std::string ErrMsg; llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz"); std::vector<const char*> args; args.push_back(Ubiviz.c_str()); args.push_back(Filename.c_str()); args.push_back(0); - + if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) { - llvm::cerr << "Error viewing graph: " << ErrMsg << "\n"; + llvm::errs() << "Error viewing graph: " << ErrMsg << "\n"; } - + // Delete the directory. - Dir.eraseFromDisk(true); + Dir.eraseFromDisk(true); } diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp index 1c536b07cee2..13aecf171718 100644 --- a/lib/Frontend/Backend.cpp +++ b/lib/Frontend/Backend.cpp @@ -24,8 +24,8 @@ #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/Timer.h" #include "llvm/System/Path.h" @@ -33,7 +33,7 @@ #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/Target/TargetRegistry.h" using namespace clang; using namespace llvm; @@ -42,13 +42,14 @@ namespace { BackendAction Action; CompileOptions CompileOpts; llvm::raw_ostream *AsmOutStream; + llvm::formatted_raw_ostream FormattedOutStream; ASTContext *Context; Timer LLVMIRGeneration; Timer CodeGenerationTime; - + llvm::OwningPtr<CodeGenerator> Gen; - + llvm::Module *TheModule; llvm::TargetData *TheTargetData; @@ -71,21 +72,25 @@ namespace { bool AddEmitPasses(std::string &Error); void EmitAssembly(); - - public: - BackendConsumer(BackendAction action, Diagnostic &Diags, + + public: + BackendConsumer(BackendAction action, Diagnostic &Diags, const LangOptions &langopts, const CompileOptions &compopts, const std::string &infile, llvm::raw_ostream* OS, LLVMContext& C) : - Action(action), + Action(action), CompileOpts(compopts), - AsmOutStream(OS), + AsmOutStream(OS), LLVMIRGeneration("LLVM IR Generation Time"), CodeGenerationTime("Code Generation Time"), Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)), TheModule(0), TheTargetData(0), ModuleProvider(0), CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) { - + + if (AsmOutStream) + FormattedOutStream.setStream(*AsmOutStream, + formatted_raw_ostream::PRESERVE_STREAM); + // Enable -time-passes if -ftime-report is enabled. llvm::TimePassesIsEnabled = CompileOpts.TimePasses; } @@ -100,25 +105,25 @@ namespace { virtual void Initialize(ASTContext &Ctx) { Context = &Ctx; - + if (CompileOpts.TimePasses) LLVMIRGeneration.startTimer(); - + Gen->Initialize(Ctx); TheModule = Gen->GetModule(); ModuleProvider = new ExistingModuleProvider(TheModule); TheTargetData = new llvm::TargetData(Ctx.Target.getTargetDescription()); - + if (CompileOpts.TimePasses) LLVMIRGeneration.stopTimer(); } - + virtual void HandleTopLevelDecl(DeclGroupRef D) { PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), Context->getSourceManager(), "LLVM IR generation of declaration"); - + if (CompileOpts.TimePasses) LLVMIRGeneration.startTimer(); @@ -127,7 +132,7 @@ namespace { if (CompileOpts.TimePasses) LLVMIRGeneration.stopTimer(); } - + virtual void HandleTranslationUnit(ASTContext &C) { { PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); @@ -142,12 +147,12 @@ namespace { // EmitAssembly times and registers crash info itself. EmitAssembly(); - + // Force a flush here in case we never get released. if (AsmOutStream) - AsmOutStream->flush(); + FormattedOutStream.flush(); } - + virtual void HandleTagDeclDefinition(TagDecl *D) { PrettyStackTraceDecl CrashInfo(D, SourceLocation(), Context->getSourceManager(), @@ -158,7 +163,7 @@ namespace { virtual void CompleteTentativeDefinition(VarDecl *D) { Gen->CompleteTentativeDefinition(D); } - }; + }; } FunctionPassManager *BackendConsumer::getCodeGenPasses() const { @@ -193,16 +198,16 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { return true; if (Action == Backend_EmitBC) { - getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream)); + getPerModulePasses()->add(createBitcodeWriterPass(FormattedOutStream)); } else if (Action == Backend_EmitLL) { - getPerModulePasses()->add(createPrintModulePass(AsmOutStream)); + getPerModulePasses()->add(createPrintModulePass(&FormattedOutStream)); } else { bool Fast = CompileOpts.OptimizationLevel == 0; // Create the TargetMachine for generating code. - const TargetMachineRegistry::entry *TME = - TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error); - if (!TME) { + std::string Triple = TheModule->getTargetTriple(); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); + if (!TheTarget) { Error = std::string("Unable to get target machine: ") + Error; return false; } @@ -211,18 +216,18 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { if (CompileOpts.CPU.size() || CompileOpts.Features.size()) { SubtargetFeatures Features; Features.setCPU(CompileOpts.CPU); - for (std::vector<std::string>::iterator + for (std::vector<std::string>::iterator it = CompileOpts.Features.begin(), ie = CompileOpts.Features.end(); it != ie; ++it) Features.AddFeature(*it); FeaturesStr = Features.getString(); } - TargetMachine *TM = TME->CtorFn(*TheModule, FeaturesStr); - + TargetMachine *TM = TheTarget->createTargetMachine(Triple, FeaturesStr); + // Set register scheduler & allocation policy. RegisterScheduler::setDefault(createDefaultScheduler); - RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator : - createLinearScanRegisterAllocator); + RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator : + createLinearScanRegisterAllocator); // From llvm-gcc: // If there are passes we have to run on the entire module, we do codegen @@ -240,7 +245,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { // Normal mode, emit a .s file by running the code generator. // Note, this also adds codegenerator level optimization passes. - switch (TM->addPassesToEmitFile(*PM, *AsmOutStream, + switch (TM->addPassesToEmitFile(*PM, FormattedOutStream, TargetMachine::AssemblyFile, OptLevel)) { default: case FileModel::Error: @@ -249,7 +254,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { case FileModel::AsmFile: break; } - + if (TM->addPassesToEmitFileFinish(*CodeGenPasses, (MachineCodeEmitter *)0, OptLevel)) { Error = "Unable to interface with target machine!\n"; @@ -287,8 +292,8 @@ void BackendConsumer::CreatePasses() { // For now we always create per module passes. PassManager *PM = getPerModulePasses(); - llvm::createStandardModulePasses(PM, CompileOpts.OptimizationLevel, - CompileOpts.OptimizeSize, + llvm::createStandardModulePasses(PM, CompileOpts.OptimizationLevel, + CompileOpts.OptimizeSize, CompileOpts.UnitAtATime, CompileOpts.UnrollLoops, CompileOpts.SimplifyLibCalls, @@ -297,12 +302,12 @@ void BackendConsumer::CreatePasses() { } /// EmitAssembly - Handle interaction with LLVM backend to generate -/// actual machine code. +/// actual machine code. void BackendConsumer::EmitAssembly() { // Silently ignore if we weren't initialized for some reason. if (!TheModule || !TheTargetData) return; - + TimeRegion Region(CompileOpts.TimePasses ? &CodeGenerationTime : 0); // Make sure IR generation is happy with the module. This is @@ -323,7 +328,7 @@ void BackendConsumer::EmitAssembly() { std::string Error; if (!AddEmitPasses(Error)) { // FIXME: Don't fail this way. - llvm::cerr << "ERROR: " << Error << "\n"; + llvm::errs() << "ERROR: " << Error << "\n"; ::exit(1); } @@ -332,19 +337,19 @@ void BackendConsumer::EmitAssembly() { if (PerFunctionPasses) { PrettyStackTraceString CrashInfo("Per-function optimization"); - + PerFunctionPasses->doInitialization(); for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isDeclaration()) PerFunctionPasses->run(*I); PerFunctionPasses->doFinalization(); } - + if (PerModulePasses) { PrettyStackTraceString CrashInfo("Per-module optimization passes"); PerModulePasses->run(*M); } - + if (CodeGenPasses) { PrettyStackTraceString CrashInfo("Code generation"); CodeGenPasses->doInitialization(); diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index f8d09dbee89e..e3ec78627da0 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -1,9 +1,9 @@ set(LLVM_NO_RTTI 1) add_clang_library(clangFrontend - AnalysisConsumer.cpp ASTConsumers.cpp ASTUnit.cpp + AnalysisConsumer.cpp Backend.cpp CacheTokens.cpp DeclXML.cpp @@ -26,7 +26,6 @@ add_clang_library(clangFrontend PlistDiagnostics.cpp PrintParserCallbacks.cpp PrintPreprocessedOutput.cpp - ResolveLocation.cpp RewriteBlocks.cpp RewriteMacros.cpp RewriteObjC.cpp @@ -38,6 +37,14 @@ add_clang_library(clangFrontend Warnings.cpp ) +IF(MSVC) + get_target_property(NON_ANSI_COMPILE_FLAGS clangFrontend COMPILE_FLAGS) + string(REPLACE /Za + "" NON_ANSI_COMPILE_FLAGS + ${NON_ANSI_COMPILE_FLAGS}) + set_target_properties(clangFrontend PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS}) +ENDIF(MSVC) + add_dependencies(clangFrontend ClangDiagnosticFrontend ClangDiagnosticLex diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 0065828c6de8..e7fc5660ad20 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -20,12 +20,11 @@ #include "clang/Basic/OnDiskHashTable.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Streams.h" +#include "llvm/ADT/StringMap.h" // FIXME: put this somewhere else? #ifndef S_ISDIR @@ -41,19 +40,19 @@ using namespace clang::io; namespace { class VISIBILITY_HIDDEN PTHEntry { - Offset TokenData, PPCondData; + Offset TokenData, PPCondData; -public: +public: PTHEntry() {} PTHEntry(Offset td, Offset ppcd) : TokenData(td), PPCondData(ppcd) {} - - Offset getTokenOffset() const { return TokenData; } + + Offset getTokenOffset() const { return TokenData; } Offset getPPCondTableOffset() const { return PPCondData; } }; - - + + class VISIBILITY_HIDDEN PTHEntryKeyVariant { union { const FileEntry* FE; const char* Path; }; enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind; @@ -67,15 +66,15 @@ public: PTHEntryKeyVariant(const char* path) : Path(path), Kind(IsNoExist), StatBuf(0) {} - + bool isFile() const { return Kind == IsFE; } - + const char* getCString() const { return Kind == IsFE ? FE->getName() : Path; } - + unsigned getKind() const { return (unsigned) Kind; } - + void EmitData(llvm::raw_ostream& Out) { switch (Kind) { case IsFE: @@ -99,45 +98,45 @@ public: break; } } - + unsigned getRepresentationLength() const { return Kind == IsNoExist ? 0 : 4 + 4 + 2 + 8 + 8; } }; - + class VISIBILITY_HIDDEN FileEntryPTHEntryInfo { public: typedef PTHEntryKeyVariant key_type; typedef key_type key_type_ref; - + typedef PTHEntry data_type; typedef const PTHEntry& data_type_ref; - + static unsigned ComputeHash(PTHEntryKeyVariant V) { return BernsteinHash(V.getCString()); } - - static std::pair<unsigned,unsigned> + + static std::pair<unsigned,unsigned> EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V, const PTHEntry& E) { unsigned n = strlen(V.getCString()) + 1 + 1; ::Emit16(Out, n); - + unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0); ::Emit8(Out, m); return std::make_pair(n, m); } - + static void EmitKey(llvm::raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){ // Emit the entry kind. ::Emit8(Out, (unsigned) V.getKind()); // Emit the string. Out.write(V.getCString(), n - 1); } - - static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V, + + static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V, const PTHEntry& E, unsigned) { @@ -147,12 +146,12 @@ public: ::Emit32(Out, E.getTokenOffset()); ::Emit32(Out, E.getPPCondTableOffset()); } - + // Emit any other data associated with the key (i.e., stat information). V.EmitData(Out); - } + } }; - + class OffsetOpt { bool valid; Offset off; @@ -181,16 +180,16 @@ class VISIBILITY_HIDDEN PTHWriter { //// Get the persistent id for the given IdentifierInfo*. uint32_t ResolveID(const IdentifierInfo* II); - + /// Emit a token to the PTH file. void EmitToken(const Token& T); void Emit8(uint32_t V) { Out << (unsigned char)(V); } - + void Emit16(uint32_t V) { ::Emit16(Out, V); } - + void Emit24(uint32_t V) { Out << (unsigned char)(V); Out << (unsigned char)(V >> 8); @@ -203,13 +202,13 @@ class VISIBILITY_HIDDEN PTHWriter { void EmitBuf(const char *Ptr, unsigned NumBytes) { Out.write(Ptr, NumBytes); } - + /// EmitIdentifierTable - Emits two tables to the PTH file. The first is /// a hashtable mapping from identifier strings to persistent IDs. /// The second is a straight table mapping from persistent IDs to string data /// (the keys of the first table). std::pair<Offset, Offset> EmitIdentifierTable(); - + /// EmitFileTable - Emit a table mapping from file name strings to PTH /// token data. Offset EmitFileTable() { return PM.Emit(Out); } @@ -218,23 +217,23 @@ class VISIBILITY_HIDDEN PTHWriter { Offset EmitCachedSpellings(); public: - PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp) + PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp) : Out(out), PP(pp), idcount(0), CurStrOffset(0) {} - + PTHMap &getPM() { return PM; } void GeneratePTH(const std::string *MainFile = 0); }; } // end anonymous namespace - -uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) { + +uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) { // Null IdentifierInfo's map to the persistent ID 0. if (!II) return 0; - + IDMap::iterator I = IM.find(II); if (I != IM.end()) return I->second; // We've already added 1. - + IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL. return idcount; } @@ -243,7 +242,7 @@ void PTHWriter::EmitToken(const Token& T) { // Emit the token kind, flags, and length. Emit32(((uint32_t) T.getKind()) | ((((uint32_t) T.getFlags())) << 8)| (((uint32_t) T.getLength()) << 16)); - + if (!T.isLiteral()) { Emit32(ResolveID(T.getIdentifierInfo())); } else { @@ -254,18 +253,18 @@ void PTHWriter::EmitToken(const Token& T) { // Get the string entry. llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s, s+len); - + // If this is a new string entry, bump the PTH offset. if (!E->getValue().hasOffset()) { E->getValue().setOffset(CurStrOffset); StrEntries.push_back(E); CurStrOffset += len + 1; } - + // Emit the relative offset into the PTH file for the spelling string. Emit32(E->getValue().getOffset()); } - + // Emit the offset into the original source file of this token so that we // can reconstruct its SourceLocation. Emit32(PP.getSourceManager().getFileOffset(T.getLocation())); @@ -276,14 +275,14 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { // This speed up reading them back in. Pad(Out, 4); Offset off = (Offset) Out.tell(); - + // Keep track of matching '#if' ... '#endif'. typedef std::vector<std::pair<Offset, unsigned> > PPCondTable; PPCondTable PPCond; std::vector<unsigned> PPStartCond; bool ParsingPreprocessorDirective = false; Token Tok; - + do { L.LexFromRawLexer(Tok); NextToken: @@ -301,7 +300,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { EmitToken(Tmp); ParsingPreprocessorDirective = false; } - + if (Tok.is(tok::identifier)) { Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok)); EmitToken(Tok); @@ -321,39 +320,39 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { // If we see the start of line, then we had a null directive "#". if (Tok.isAtStartOfLine()) goto NextToken; - + // Did we see 'include'/'import'/'include_next'? if (Tok.isNot(tok::identifier)) { EmitToken(Tok); continue; } - + IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok); Tok.setIdentifierInfo(II); tok::PPKeywordKind K = II->getPPKeywordID(); - + ParsingPreprocessorDirective = true; - + switch (K) { case tok::pp_not_keyword: // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass // them through. default: break; - + case tok::pp_include: case tok::pp_import: - case tok::pp_include_next: { + case tok::pp_include_next: { // Save the 'include' token. EmitToken(Tok); // Lex the next token as an include string. L.setParsingPreprocessorDirective(true); - L.LexIncludeFilename(Tok); + L.LexIncludeFilename(Tok); L.setParsingPreprocessorDirective(false); assert(!Tok.isAtStartOfLine()); if (Tok.is(tok::identifier)) Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok)); - + break; } case tok::pp_if: @@ -375,11 +374,11 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { assert(PPCond.size() > PPStartCond.back()); assert(PPCond[PPStartCond.back()].second == 0); PPCond[PPStartCond.back()].second = index; - PPStartCond.pop_back(); - // Add the new entry to PPCond. + PPStartCond.pop_back(); + // Add the new entry to PPCond. PPCond.push_back(std::make_pair(HashOff, index)); EmitToken(Tok); - + // Some files have gibberish on the same line as '#endif'. // Discard these tokens. do @@ -387,7 +386,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine()); // We have the next token in hand. // Don't immediately lex the next one. - goto NextToken; + goto NextToken; } case tok::pp_elif: case tok::pp_else: { @@ -408,7 +407,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { } } } - + EmitToken(Tok); } while (Tok.isNot(tok::eof)); @@ -436,11 +435,11 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { Offset PTHWriter::EmitCachedSpellings() { // Write each cached strings to the PTH file. Offset SpellingsOff = Out.tell(); - + for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I) EmitBuf((*I)->getKeyData(), (*I)->getKeyLength()+1 /*nul included*/); - + return SpellingsOff; } @@ -448,12 +447,12 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) { // Generate the prologue. Out << "cfe-pth"; Emit32(PTHManager::Version); - + // Leave 4 words for the prologue. Offset PrologueOffset = Out.tell(); for (unsigned i = 0; i < 4; ++i) Emit32(0); - + // Write the name of the MainFile. if (MainFile && !MainFile->empty()) { Emit16(MainFile->length()); @@ -463,17 +462,17 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) { Emit16(0); } Emit8(0); - + // Iterate over all the files in SourceManager. Create a lexer // for each file and cache the tokens. SourceManager &SM = PP.getSourceManager(); const LangOptions &LOpts = PP.getLangOptions(); - + for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(), E = SM.fileinfo_end(); I != E; ++I) { const SrcMgr::ContentCache &C = *I->second; const FileEntry *FE = C.Entry; - + // FIXME: Handle files with non-absolute paths. llvm::sys::Path P(FE->getName()); if (!P.isAbsolute()) @@ -489,13 +488,13 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) { // Write out the identifier table. const std::pair<Offset,Offset> &IdTableOff = EmitIdentifierTable(); - + // Write out the cached strings table. Offset SpellingOff = EmitCachedSpellings(); - + // Write out the file table. - Offset FileTableOff = EmitFileTable(); - + Offset FileTableOff = EmitFileTable(); + // Finally, write the prologue. Out.seek(PrologueOffset); Emit32(IdTableOff.first); @@ -515,20 +514,20 @@ class StatListener : public StatSysCallCache { public: StatListener(PTHMap &pm) : PM(pm) {} ~StatListener() {} - + int stat(const char *path, struct stat *buf) { int result = ::stat(path, buf); - + if (result != 0) // Failed 'stat'. PM.insert(path, PTHEntry()); else if (S_ISDIR(buf->st_mode)) { // Only cache directories with absolute paths. if (!llvm::sys::Path(path).isAbsolute()) return result; - + PM.insert(PTHEntryKeyVariant(buf, path), PTHEntry()); } - + return result; } }; @@ -541,27 +540,27 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { const FileEntry *MainFile = SrcMgr.getFileEntryForID(SrcMgr.getMainFileID()); llvm::sys::Path MainFilePath(MainFile->getName()); std::string MainFileName; - + if (!MainFilePath.isAbsolute()) { llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory(); - P.appendComponent(MainFilePath.toString()); - MainFileName = P.toString(); + P.appendComponent(MainFilePath.str()); + MainFileName = P.str(); } else { - MainFileName = MainFilePath.toString(); + MainFileName = MainFilePath.str(); } // Create the PTHWriter. PTHWriter PW(*OS, PP); - + // Install the 'stat' system call listener in the FileManager. PP.getFileManager().setStatCache(new StatListener(PW.getPM())); - + // Lex through the entire file. This will populate SourceManager with // all of the header information. Token Tok; PP.EnterMainSourceFile(); do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); - + // Generate the PTH file. PP.getFileManager().setStatCache(0); PW.GeneratePTH(&MainFileName); @@ -580,32 +579,32 @@ class VISIBILITY_HIDDEN PTHIdentifierTableTrait { public: typedef PTHIdKey* key_type; typedef key_type key_type_ref; - + typedef uint32_t data_type; typedef data_type data_type_ref; - + static unsigned ComputeHash(PTHIdKey* key) { return BernsteinHash(key->II->getName()); } - - static std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) { + + static std::pair<unsigned,unsigned> + EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) { unsigned n = strlen(key->II->getName()) + 1; ::Emit16(Out, n); return std::make_pair(n, sizeof(uint32_t)); } - + static void EmitKey(llvm::raw_ostream& Out, PTHIdKey* key, unsigned n) { // Record the location of the key data. This is used when generating // the mapping from persistent IDs to strings. key->FileOffset = Out.tell(); Out.write(key->II->getName(), n); } - + static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID, unsigned) { ::Emit32(Out, pID); - } + } }; } // end anonymous namespace @@ -624,7 +623,7 @@ std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() { // Create the hashtable. OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap; - + // Generate mapping from persistent IDs -> IdentifierInfo*. for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) { // Decrement by 1 because we are using a vector for the lookup and @@ -632,27 +631,27 @@ std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() { assert(I->second > 0); assert(I->second-1 < idcount); unsigned idx = I->second-1; - + // Store the mapping from persistent ID to IdentifierInfo* IIDMap[idx].II = I->first; - + // Store the reverse mapping in a hashtable. IIOffMap.insert(&IIDMap[idx], I->second); } - + // Write out the inverse map first. This causes the PCIDKey entries to // record PTH file offsets for the string data. This is used to write // the second table. Offset StringTableOffset = IIOffMap.Emit(Out); - - // Now emit the table mapping from persistent IDs to PTH file offsets. + + // Now emit the table mapping from persistent IDs to PTH file offsets. Offset IDOff = Out.tell(); Emit32(idcount); // Emit the number of identifiers. for (unsigned i = 0 ; i < idcount; ++i) Emit32(IIDMap[i].FileOffset); - + // Finally, release the inverse map. free(IIDMap); - + return std::make_pair(IDOff, StringTableOffset); } diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp index 68f931fb6c69..b981fc41daa9 100644 --- a/lib/Frontend/DeclXML.cpp +++ b/lib/Frontend/DeclXML.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the XML document class, which provides the means to +// This file implements the XML document class, which provides the means to // dump out the AST in a XML form that exposes type details and other fields. // //===----------------------------------------------------------------------===// @@ -18,22 +18,18 @@ namespace clang { -//--------------------------------------------------------- -class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> -{ +//--------------------------------------------------------- +class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> { DocumentXML& Doc; - void addSubNodes(FunctionDecl* FD) - { - for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) - { + void addSubNodes(FunctionDecl* FD) { + for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { Visit(FD->getParamDecl(i)); Doc.toParent(); } } - void addSubNodes(RecordDecl* RD) - { + void addSubNodes(RecordDecl* RD) { for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { Visit(*i); @@ -41,8 +37,7 @@ class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> } } - void addSubNodes(EnumDecl* ED) - { + void addSubNodes(EnumDecl* ED) { for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(), e = ED->enumerator_end(); i != e; ++i) { Visit(*i); @@ -50,54 +45,37 @@ class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> } } - void addSubNodes(EnumConstantDecl* ECD) - { - if (ECD->getInitExpr()) - { + void addSubNodes(EnumConstantDecl* ECD) { + if (ECD->getInitExpr()) Doc.PrintStmt(ECD->getInitExpr()); - } } - void addSubNodes(FieldDecl* FdD) - { + void addSubNodes(FieldDecl* FdD) { if (FdD->isBitField()) - { Doc.PrintStmt(FdD->getBitWidth()); - } } - void addSubNodes(VarDecl* V) - { - if (V->getInit()) - { + void addSubNodes(VarDecl* V) { + if (V->getInit()) Doc.PrintStmt(V->getInit()); - } } - void addSubNodes(ParmVarDecl* argDecl) - { + void addSubNodes(ParmVarDecl* argDecl) { if (argDecl->getDefaultArg()) - { Doc.PrintStmt(argDecl->getDefaultArg()); - } } - void addSpecialAttribute(const char* pName, EnumDecl* ED) - { + void addSpecialAttribute(const char* pName, EnumDecl* ED) { const QualType& enumType = ED->getIntegerType(); if (!enumType.isNull()) - { Doc.addAttribute(pName, enumType); - } } - void addIdAttribute(LinkageSpecDecl* ED) - { + void addIdAttribute(LinkageSpecDecl* ED) { Doc.addAttribute("id", ED); } - void addIdAttribute(NamedDecl* ND) - { + void addIdAttribute(NamedDecl* ND) { Doc.addAttribute("id", ND); } @@ -107,11 +85,11 @@ public: #define NODE_XML( CLASS, NAME ) \ void Visit##CLASS(CLASS* T) \ { \ - Doc.addSubNode(NAME); + Doc.addSubNode(NAME); #define ID_ATTRIBUTE_XML addIdAttribute(T); -#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); -#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); #define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation()); #define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T); @@ -120,14 +98,14 @@ public: const char* pAttributeName = NAME; \ const bool optional = false; \ switch (T->FN) { \ - default: assert(0 && "unknown enum value"); + default: assert(0 && "unknown enum value"); #define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ { \ const char* pAttributeName = NAME; \ const bool optional = true; \ switch (T->FN) { \ - default: assert(0 && "unknown enum value"); + default: assert(0 && "unknown enum value"); #define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; #define END_ENUM_XML } } @@ -141,12 +119,10 @@ public: }; -//--------------------------------------------------------- -void DocumentXML::writeDeclToXML(Decl *D) -{ +//--------------------------------------------------------- +void DocumentXML::writeDeclToXML(Decl *D) { DeclPrinter(*this).Visit(D); - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (Stmt *Body = FD->getBody()) { addSubNode("Body"); PrintStmt(Body); @@ -156,6 +132,6 @@ void DocumentXML::writeDeclToXML(Decl *D) toParent(); } -//--------------------------------------------------------- +//--------------------------------------------------------- } // NS clang diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index c8a654cff2c4..81d1179f28e3 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -40,8 +40,8 @@ private: void OutputDependencyFile(); public: - DependencyFileCallback(const Preprocessor *_PP, - llvm::raw_ostream *_OS, + DependencyFileCallback(const Preprocessor *_PP, + llvm::raw_ostream *_OS, const std::vector<std::string> &_Targets, bool _IncludeSystemHeaders, bool _PhonyTarget) @@ -67,8 +67,8 @@ void clang::AttachDependencyFileGen(Preprocessor *PP, llvm::raw_ostream *OS, bool PhonyTarget) { assert(!Targets.empty() && "Target required for dependency generation"); - DependencyFileCallback *PPDep = - new DependencyFileCallback(PP, OS, Targets, IncludeSystemHeaders, + DependencyFileCallback *PPDep = + new DependencyFileCallback(PP, OS, Targets, IncludeSystemHeaders, PhonyTarget); PP->setPPCallbacks(PPDep); } @@ -91,16 +91,16 @@ void DependencyFileCallback::FileChanged(SourceLocation Loc, SrcMgr::CharacteristicKind FileType) { if (Reason != PPCallbacks::EnterFile) return; - + // Dependency generation really does want to go all the way to the // file entry for a source location to find out what is depended on. // We do not want #line markers to affect dependency generation! SourceManager &SM = PP->getSourceManager(); - + const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(SM.getInstantiationLoc(Loc))); if (FE == 0) return; - + const char *Filename = FE->getName(); if (!FileMatchesDepCriteria(Filename, FileType)) return; @@ -138,7 +138,7 @@ void DependencyFileCallback::OutputDependencyFile() { *OS << ':'; Columns += 1; - + // Now add each dependency in the order it was seen, but avoiding // duplicates. for (std::vector<std::string>::iterator I = Files.begin(), diff --git a/lib/Frontend/DiagChecker.cpp b/lib/Frontend/DiagChecker.cpp index c0f5d141be06..26bb6ccfa7c7 100644 --- a/lib/Frontend/DiagChecker.cpp +++ b/lib/Frontend/DiagChecker.cpp @@ -55,33 +55,33 @@ static void EmitError(Preprocessor &PP, SourceLocation Pos, const char *String){ /// FindDiagnostics - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in a diagnostic list. -/// +/// static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, DiagList &ExpectedDiags, Preprocessor &PP, SourceLocation Pos, const char *ExpectedStr) { const char *CommentEnd = CommentStart+CommentLen; unsigned ExpectedStrLen = strlen(ExpectedStr); - + // Find all expected-foo diagnostics in the string and add them to // ExpectedDiags. while (CommentStart != CommentEnd) { CommentStart = std::find(CommentStart, CommentEnd, 'e'); if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return; - + // If this isn't expected-foo, ignore it. if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) { ++CommentStart; continue; } - + CommentStart += ExpectedStrLen; - + // Skip whitespace. while (CommentStart != CommentEnd && isspace(CommentStart[0])) ++CommentStart; - + // Default, if we find the '{' now, is 1 time. int Times = 1; int Temp = 0; @@ -94,12 +94,12 @@ static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, } if (Temp > 0) Times = Temp; - + // Skip whitespace again. while (CommentStart != CommentEnd && isspace(CommentStart[0])) ++CommentStart; - + // We should have a {{ now. if (CommentEnd-CommentStart < 2 || CommentStart[0] != '{' || CommentStart[1] != '{') { @@ -119,7 +119,7 @@ static void FindDiagnostics(const char *CommentStart, unsigned CommentLen, EmitError(PP, Pos, "cannot find end ('}}') of expected string"); return; } - + if (ExpectedEnd[1] == '}') break; @@ -147,10 +147,10 @@ static void FindExpectedDiags(Preprocessor &PP, // Create a raw lexer to pull all the comments out of the main file. We don't // want to look in #include'd headers for expected-error strings. FileID FID = PP.getSourceManager().getMainFileID(); - + // Create a lexer to lex all the tokens of the main file in raw mode. Lexer RawLex(FID, PP.getSourceManager(), PP.getLangOptions()); - + // Return comments as tokens, this is how we find expected diagnostics. RawLex.SetCommentRetentionState(true); @@ -159,11 +159,11 @@ static void FindExpectedDiags(Preprocessor &PP, while (Tok.isNot(tok::eof)) { RawLex.Lex(Tok); if (!Tok.is(tok::comment)) continue; - + std::string Comment = PP.getSpelling(Tok); if (Comment.empty()) continue; - + // Find all expected errors. FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP, Tok.getLocation(), "expected-error"); @@ -182,7 +182,7 @@ static void FindExpectedDiags(Preprocessor &PP, /// seen diagnostics. If there's anything in it, then something unexpected /// happened. Print the map out in a nice format and return "true". If the map /// is empty and we're not going to print things, then return "false". -/// +/// static bool PrintProblem(SourceManager &SourceMgr, const_diag_iterator diag_begin, const_diag_iterator diag_end, @@ -201,7 +201,7 @@ static bool PrintProblem(SourceManager &SourceMgr, /// CompareDiagLists - Compare two diagnostic lists and return the difference /// between them. -/// +/// static bool CompareDiagLists(SourceManager &SourceMgr, const_diag_iterator d1_begin, const_diag_iterator d1_end, @@ -245,7 +245,7 @@ static bool CompareDiagLists(SourceManager &SourceMgr, /// CheckResults - This compares the expected results to those that /// were actually reported. It emits any discrepencies. Return "true" if there /// were problems. Return "false" otherwise. -/// +/// static bool CheckResults(Preprocessor &PP, const DiagList &ExpectedErrors, const DiagList &ExpectedWarnings, diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp index 19a757303f1b..d92d4cb7b8de 100644 --- a/lib/Frontend/DocumentXML.cpp +++ b/lib/Frontend/DocumentXML.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the XML document class, which provides the means to +// This file implements the XML document class, which provides the means to // dump out the AST in a XML form that exposes type details and other fields. // //===----------------------------------------------------------------------===// @@ -20,23 +20,19 @@ namespace clang { -//--------------------------------------------------------- +//--------------------------------------------------------- DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) : Out(out), Ctx(0), - HasCurrentNodeSubNodes(false) -{ + HasCurrentNodeSubNodes(false) { NodeStack.push(rootName); Out << "<?xml version=\"1.0\"?>\n<" << rootName; } -//--------------------------------------------------------- -DocumentXML& DocumentXML::addSubNode(const std::string& name) -{ +//--------------------------------------------------------- +DocumentXML& DocumentXML::addSubNode(const std::string& name) { if (!HasCurrentNodeSubNodes) - { Out << ">\n"; - } NodeStack.push(name); HasCurrentNodeSubNodes = false; Indent(); @@ -44,46 +40,38 @@ DocumentXML& DocumentXML::addSubNode(const std::string& name) return *this; } -//--------------------------------------------------------- -void DocumentXML::Indent() -{ +//--------------------------------------------------------- +void DocumentXML::Indent() { for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i) Out << ' '; } -//--------------------------------------------------------- -DocumentXML& DocumentXML::toParent() -{ - assert(NodeStack.size() > 1 && "to much backtracking"); +//--------------------------------------------------------- +DocumentXML& DocumentXML::toParent() { + assert(NodeStack.size() > 1 && "too much backtracking"); - if (HasCurrentNodeSubNodes) - { + if (HasCurrentNodeSubNodes) { Indent(); Out << "</" << NodeStack.top() << ">\n"; - } - else - { + } else Out << "/>\n"; - } NodeStack.pop(); HasCurrentNodeSubNodes = true; - return *this; + return *this; } -//--------------------------------------------------------- +//--------------------------------------------------------- namespace { enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST }; -unsigned getNewId(tIdType idType) -{ +unsigned getNewId(tIdType idType) { static unsigned int idCounts[ID_LAST] = { 0 }; return ++idCounts[idType]; } -//--------------------------------------------------------- -inline std::string getPrefixedId(unsigned uId, tIdType idType) -{ +//--------------------------------------------------------- +inline std::string getPrefixedId(unsigned uId, tIdType idType) { static const char idPrefix[ID_LAST] = { '_', 'f', 'l' }; char buffer[20]; char* BufPtr = llvm::utohex_buffer(uId, buffer + 20); @@ -91,25 +79,22 @@ inline std::string getPrefixedId(unsigned uId, tIdType idType) return BufPtr; } -//--------------------------------------------------------- +//--------------------------------------------------------- template<class T, class V> -bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) -{ +bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) { typename T::iterator i = idMap.find(value); bool toAdd = i == idMap.end(); - if (toAdd) - { + if (toAdd) idMap.insert(typename T::value_type(value, getNewId(idType))); - } return toAdd; } } // anon NS -//--------------------------------------------------------- -std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len) -{ +//--------------------------------------------------------- +std::string DocumentXML::escapeString(const char* pStr, + std::string::size_type len) { std::string value; value.reserve(len + 1); char buffer[16]; @@ -118,8 +103,7 @@ std::string DocumentXML::escapeString(const char* pStr, std::string::size_type l default: if (isprint(C)) value += C; - else - { + else { sprintf(buffer, "\\%03o", C); value += buffer; } @@ -142,26 +126,24 @@ std::string DocumentXML::escapeString(const char* pStr, std::string::size_type l return value; } -//--------------------------------------------------------- -void DocumentXML::finalize() -{ +//--------------------------------------------------------- +void DocumentXML::finalize() { assert(NodeStack.size() == 1 && "not completely backtracked"); addSubNode("ReferenceSection"); addSubNode("Types"); - for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end(); i != e; ++i) - { - if (i->first.getCVRQualifiers() != 0) - { + for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end(); + i != e; ++i) { + if (i->first.hasQualifiers()) { writeTypeToXML(i->first); addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); toParent(); } } - for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i) - { + for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), + e = BasicTypes.end(); i != e; ++i) { writeTypeToXML(i->first); addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); toParent(); @@ -170,31 +152,26 @@ void DocumentXML::finalize() toParent().addSubNode("Contexts"); - for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(), e = Contexts.end(); i != e; ++i) - { + for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(), + e = Contexts.end(); i != e; ++i) { addSubNode(i->first->getDeclKindName()); addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); - if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first)) { + if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first)) addAttribute("name", ND->getNameAsString()); - } - if (const TagDecl *TD = dyn_cast<TagDecl>(i->first)) { + if (const TagDecl *TD = dyn_cast<TagDecl>(i->first)) addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL)); - } - else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first)) { - addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAsFunctionType()], ID_NORMAL)); - } + else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first)) + addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAs<FunctionType>()], ID_NORMAL)); if (const DeclContext* parent = i->first->getParent()) - { addAttribute("context", parent); - } toParent(); } toParent().addSubNode("Files"); - for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(), e = SourceFiles.end(); i != e; ++i) - { + for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(), + e = SourceFiles.end(); i != e; ++i) { addSubNode("File"); addAttribute("id", getPrefixedId(i->second, ID_FILE)); addAttribute("name", escapeString(i->first.c_str(), i->first.size())); @@ -202,40 +179,40 @@ void DocumentXML::finalize() } toParent().toParent(); - + // write the root closing node (which has always subnodes) Out << "</" << NodeStack.top() << ">\n"; } -//--------------------------------------------------------- -void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType) -{ +//--------------------------------------------------------- +void DocumentXML::addAttribute(const char* pAttributeName, + const QualType& pType) { addTypeRecursively(pType); addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL)); } -//--------------------------------------------------------- -void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType) -{ +//--------------------------------------------------------- +void DocumentXML::addPtrAttribute(const char* pAttributeName, + const Type* pType) { addTypeRecursively(pType); addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL)); } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addTypeRecursively(const QualType& pType) { if (addToMap(Types, pType)) { addTypeRecursively(pType.getTypePtr()); // beautifier: a non-qualified type shall be transparent - if (pType.getCVRQualifiers() == 0) + if (!pType.hasQualifiers()) { - Types[pType] = BasicTypes[pType.getTypePtr()]; + Types[pType] = BasicTypes[pType.getTypePtr()]; } } } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addTypeRecursively(const Type* pType) { if (addToMap(BasicTypes, pType)) @@ -243,7 +220,7 @@ void DocumentXML::addTypeRecursively(const Type* pType) addParentTypes(pType); /* // FIXME: doesn't work in the immediate streaming approach - if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType)) + if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType)) { addSubNode("VariableArraySizeExpression"); PrintStmt(VAT->getSizeExpr()); @@ -253,14 +230,14 @@ void DocumentXML::addTypeRecursively(const Type* pType) } } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC) { addContextsRecursively(DC); addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL)); } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D) { if (const DeclContext* DC = dyn_cast<DeclContext>(D)) @@ -275,22 +252,22 @@ void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D } } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D) { addPtrAttribute(pName, static_cast<const DeclContext*>(D)); } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addContextsRecursively(const DeclContext *DC) { if (DC != 0 && addToMap(Contexts, DC)) { addContextsRecursively(DC->getParent()); - } + } } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addSourceFileAttribute(const std::string& fileName) { addToMap(SourceFiles, fileName, ID_FILE); @@ -298,7 +275,7 @@ void DocumentXML::addSourceFileAttribute(const std::string& fileName) } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L) { addToMap(Labels, L, ID_LABEL); @@ -306,13 +283,13 @@ void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L) } -//--------------------------------------------------------- +//--------------------------------------------------------- PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) { SourceManager& SM = Ctx->getSourceManager(); SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); PresumedLoc PLoc; - if (!SpellingLoc.isInvalid()) + if (!SpellingLoc.isInvalid()) { PLoc = SM.getPresumedLoc(SpellingLoc); addSourceFileAttribute(PLoc.getFilename()); @@ -323,18 +300,18 @@ PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) return PLoc; } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::addLocationRange(const SourceRange& R) { PresumedLoc PStartLoc = addLocation(R.getBegin()); - if (R.getBegin() != R.getEnd()) + if (R.getBegin() != R.getEnd()) { SourceManager& SM = Ctx->getSourceManager(); SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd()); - if (!SpellingLoc.isInvalid()) + if (!SpellingLoc.isInvalid()) { PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc); - if (PStartLoc.isInvalid() || + if (PStartLoc.isInvalid() || strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) { addToMap(SourceFiles, PLoc.getFilename(), ID_FILE); addAttribute("endfile", PLoc.getFilename()); @@ -345,17 +322,17 @@ void DocumentXML::addLocationRange(const SourceRange& R) addAttribute("endcol", PLoc.getColumn()); } else { addAttribute("endcol", PLoc.getColumn()); - } + } } } } -//--------------------------------------------------------- +//--------------------------------------------------------- void DocumentXML::PrintDecl(Decl *D) { writeDeclToXML(D); } -//--------------------------------------------------------- +//--------------------------------------------------------- } // NS clang diff --git a/lib/Frontend/FixItRewriter.cpp b/lib/Frontend/FixItRewriter.cpp index 1ed89d75a9c9..dddcaa97e2ff 100644 --- a/lib/Frontend/FixItRewriter.cpp +++ b/lib/Frontend/FixItRewriter.cpp @@ -16,10 +16,11 @@ #include "clang/Frontend/FixItRewriter.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/FrontendDiagnostic.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/Support/Streams.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" +#include "llvm/ADT/OwningPtr.h" +#include <cstdio> + using namespace clang; FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr, @@ -33,7 +34,7 @@ FixItRewriter::~FixItRewriter() { Diags.setClient(Client); } -bool FixItRewriter::WriteFixedFile(const std::string &InFileName, +bool FixItRewriter::WriteFixedFile(const std::string &InFileName, const std::string &OutFileName) { if (NumFailures > 0) { Diag(FullSourceLoc(), diag::warn_fixit_no_changes); @@ -44,10 +45,8 @@ bool FixItRewriter::WriteFixedFile(const std::string &InFileName, llvm::raw_ostream *OutFile; if (!OutFileName.empty()) { std::string Err; - OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(), - // set binary mode (critical for Windoze) - true, - Err); + OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(), Err, + llvm::raw_fd_ostream::F_Binary); OwnedStream.reset(OutFile); } else if (InFileName == "-") { OutFile = &llvm::outs(); @@ -57,15 +56,13 @@ bool FixItRewriter::WriteFixedFile(const std::string &InFileName, Path.eraseSuffix(); Path.appendSuffix("fixit." + Suffix); std::string Err; - OutFile = new llvm::raw_fd_ostream(Path.toString().c_str(), - // set binary mode (critical for Windoze) - true, - Err); + OutFile = new llvm::raw_fd_ostream(Path.c_str(), Err, + llvm::raw_fd_ostream::F_Binary); OwnedStream.reset(OutFile); - } + } FileID MainFileID = Rewrite.getSourceMgr().getMainFileID(); - if (const RewriteBuffer *RewriteBuf = + if (const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(MainFileID)) { *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); } else { @@ -102,7 +99,7 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel, // See if the location of the error is one that matches what the // user requested. bool AcceptableLocation = false; - const FileEntry *File + const FileEntry *File = Rewrite.getSourceMgr().getFileEntryForID( Info.getLocation().getFileID()); unsigned Line = Info.getLocation().getSpellingLineNumber(); @@ -132,14 +129,14 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel, break; } - if (Hint.InsertionLoc.isValid() && + if (Hint.InsertionLoc.isValid() && !Rewrite.isRewritable(Hint.InsertionLoc)) { CanRewrite = false; break; } } - if (!CanRewrite) { + if (!CanRewrite) { if (Info.getNumCodeModificationHints() > 0) Diag(Info.getLocation(), diag::note_fixit_in_macro); @@ -152,29 +149,28 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel, } bool Failed = false; - for (unsigned Idx = 0, Last = Info.getNumCodeModificationHints(); + for (unsigned Idx = 0, Last = Info.getNumCodeModificationHints(); Idx < Last; ++Idx) { const CodeModificationHint &Hint = Info.getCodeModificationHint(Idx); if (!Hint.RemoveRange.isValid()) { // We're adding code. - if (Rewrite.InsertStrBefore(Hint.InsertionLoc, Hint.CodeToInsert)) + if (Rewrite.InsertTextBefore(Hint.InsertionLoc, Hint.CodeToInsert)) Failed = true; continue; } - + if (Hint.CodeToInsert.empty()) { // We're removing code. if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(), Rewrite.getRangeSize(Hint.RemoveRange))) Failed = true; continue; - } - + } + // We're replacing code. if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(), Rewrite.getRangeSize(Hint.RemoveRange), - Hint.CodeToInsert.c_str(), - Hint.CodeToInsert.size())) + Hint.CodeToInsert)) Failed = true; } @@ -195,5 +191,5 @@ void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) { Diags.setClient(Client); Diags.Clear(); Diags.Report(Loc, DiagID); - Diags.setClient(this); + Diags.setClient(this); } diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp index 8be88ce38117..bc45cc422585 100644 --- a/lib/Frontend/GeneratePCH.cpp +++ b/lib/Frontend/GeneratePCH.cpp @@ -23,7 +23,6 @@ #include "llvm/System/Path.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Streams.h" #include <string> using namespace clang; @@ -32,19 +31,24 @@ using namespace llvm; namespace { class VISIBILITY_HIDDEN PCHGenerator : public SemaConsumer { const Preprocessor &PP; + const char *isysroot; llvm::raw_ostream *Out; Sema *SemaPtr; MemorizeStatCalls *StatCalls; // owned by the FileManager public: - explicit PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *Out); + explicit PCHGenerator(const Preprocessor &PP, + const char *isysroot, + llvm::raw_ostream *Out); virtual void InitializeSema(Sema &S) { SemaPtr = &S; } virtual void HandleTranslationUnit(ASTContext &Ctx); }; } -PCHGenerator::PCHGenerator(const Preprocessor &PP, llvm::raw_ostream *OS) - : PP(PP), Out(OS), SemaPtr(0), StatCalls(0) { +PCHGenerator::PCHGenerator(const Preprocessor &PP, + const char *isysroot, + llvm::raw_ostream *OS) + : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0) { // Install a stat() listener to keep track of all of the stat() // calls. @@ -56,14 +60,14 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { if (PP.getDiagnostics().hasErrorOccurred()) return; - // Write the PCH contents into a buffer + // Write the PCH contents into a buffer std::vector<unsigned char> Buffer; BitstreamWriter Stream(Buffer); PCHWriter Writer(Stream); // Emit the PCH file assert(SemaPtr && "No Sema?"); - Writer.WritePCH(*SemaPtr, StatCalls); + Writer.WritePCH(*SemaPtr, StatCalls, isysroot); // Write the generated bitstream to "Out". Out->write((char *)&Buffer.front(), Buffer.size()); @@ -73,6 +77,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { } ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP, - llvm::raw_ostream *OS) { - return new PCHGenerator(PP, OS); + llvm::raw_ostream *OS, + const char *isysroot) { + return new PCHGenerator(PP, isysroot, OS); } diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp index 9cfe0b2a6124..9d6f96c69f5d 100644 --- a/lib/Frontend/HTMLDiagnostics.cpp +++ b/lib/Frontend/HTMLDiagnostics.cpp @@ -23,10 +23,9 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Streams.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" -#include <fstream> + using namespace clang; //===----------------------------------------------------------------------===// @@ -39,44 +38,82 @@ class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient { llvm::sys::Path Directory, FilePrefix; bool createdDir, noDir; Preprocessor* PP; - std::vector<const PathDiagnostic*> BatchedDiags; + std::vector<const PathDiagnostic*> BatchedDiags; + llvm::SmallVectorImpl<std::string> *FilesMade; public: - HTMLDiagnostics(const std::string& prefix, Preprocessor* pp); + HTMLDiagnostics(const std::string& prefix, Preprocessor* pp, + llvm::SmallVectorImpl<std::string> *filesMade = 0); virtual ~HTMLDiagnostics(); - + virtual void SetPreprocessor(Preprocessor *pp) { PP = pp; } - + virtual void HandlePathDiagnostic(const PathDiagnostic* D); - + unsigned ProcessMacroPiece(llvm::raw_ostream& os, const PathDiagnosticMacroPiece& P, unsigned num); - + void HandlePiece(Rewriter& R, FileID BugFileID, const PathDiagnosticPiece& P, unsigned num, unsigned max); - + void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range, const char *HighlightStart = "<span class=\"mrange\">", const char *HighlightEnd = "</span>"); void ReportDiag(const PathDiagnostic& D); }; - + } // end anonymous namespace -HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp) +HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp, + llvm::SmallVectorImpl<std::string>* filesMade) : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false), - PP(pp) { - - // All html files begin with "report" + PP(pp), FilesMade(filesMade) { + + // All html files begin with "report" FilePrefix.appendComponent("report"); } PathDiagnosticClient* clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP, - PreprocessorFactory*) { - return new HTMLDiagnostics(prefix, PP); + PreprocessorFactory*, + llvm::SmallVectorImpl<std::string>* FilesMade) +{ + return new HTMLDiagnostics(prefix, PP, FilesMade); +} + +//===----------------------------------------------------------------------===// +// Factory for HTMLDiagnosticClients +//===----------------------------------------------------------------------===// + +namespace { +class VISIBILITY_HIDDEN HTMLDiagnosticsFactory + : public PathDiagnosticClientFactory { + + std::string Prefix; + Preprocessor *PP; +public: + HTMLDiagnosticsFactory(const std::string& prefix, Preprocessor* pp) + : Prefix(prefix), PP(pp) {} + + virtual ~HTMLDiagnosticsFactory() {} + + const char *getName() const { return "HTMLDiagnostics"; } + + PathDiagnosticClient* + createPathDiagnosticClient(llvm::SmallVectorImpl<std::string> *FilesMade) { + + return new HTMLDiagnostics(Prefix, PP, FilesMade); + } +}; +} // end anonymous namespace + +PathDiagnosticClientFactory* +clang::CreateHTMLDiagnosticClientFactory(const std::string& prefix, + Preprocessor* PP, + PreprocessorFactory*) { + return new HTMLDiagnosticsFactory(prefix, PP); } //===----------------------------------------------------------------------===// @@ -86,12 +123,12 @@ clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP, void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) { if (!D) return; - + if (D->empty()) { delete D; return; } - + const_cast<PathDiagnostic*>(D)->flattenLocations(); BatchedDiags.push_back(D); } @@ -102,7 +139,7 @@ HTMLDiagnostics::~HTMLDiagnostics() { BatchedDiags.pop_back(); ReportDiag(*D); delete D; - } + } } void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) { @@ -111,73 +148,73 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) { createdDir = true; std::string ErrorMsg; Directory.createDirectoryOnDisk(true, &ErrorMsg); - + if (!Directory.isDirectory()) { - llvm::cerr << "warning: could not create directory '" - << Directory.toString() << "'\n" - << "reason: " << ErrorMsg << '\n'; - + llvm::errs() << "warning: could not create directory '" + << Directory.str() << "'\n" + << "reason: " << ErrorMsg << '\n'; + noDir = true; - + return; } } - + if (noDir) return; - + const SourceManager &SMgr = D.begin()->getLocation().getManager(); FileID FID; - + // Verify that the entire path is from the same FileID. for (PathDiagnostic::const_iterator I = D.begin(), E = D.end(); I != E; ++I) { FullSourceLoc L = I->getLocation().asLocation().getInstantiationLoc(); - + if (FID.isInvalid()) { FID = SMgr.getFileID(L); } else if (SMgr.getFileID(L) != FID) return; // FIXME: Emit a warning? - + // Check the source ranges. for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(), RE=I->ranges_end(); RI!=RE; ++RI) { - + SourceLocation L = SMgr.getInstantiationLoc(RI->getBegin()); if (!L.isFileID() || SMgr.getFileID(L) != FID) return; // FIXME: Emit a warning? - + L = SMgr.getInstantiationLoc(RI->getEnd()); - + if (!L.isFileID() || SMgr.getFileID(L) != FID) - return; // FIXME: Emit a warning? + return; // FIXME: Emit a warning? } } - + if (FID.isInvalid()) return; // FIXME: Emit a warning? - + // Create a new rewriter to generate HTML. Rewriter R(const_cast<SourceManager&>(SMgr), PP->getLangOptions()); - - // Process the path. + + // Process the path. unsigned n = D.size(); unsigned max = n; - + for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend(); I!=E; ++I, --n) HandlePiece(R, FID, *I, n, max); - + // Add line numbers, header, footer, etc. - + // unsigned FID = R.getSourceMgr().getMainFileID(); html::EscapeText(R, FID); html::AddLineNumbers(R, FID); - + // If we have a preprocessor, relex the file and syntax highlight. // We might not have a preprocessor if we come from a deserialized AST file, // for example. - + if (PP) html::SyntaxHighlight(R, FID, *PP); // FIXME: We eventually want to use PPF to create a fresh Preprocessor, @@ -186,141 +223,121 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) { // if (PPF) html::HighlightMacros(R, FID, *PPF); // if (PP) html::HighlightMacros(R, FID, *PP); - + // Get the full directory name of the analyzed file. const FileEntry* Entry = SMgr.getFileEntryForID(FID); - + // This is a cludge; basically we want to append either the full // working directory if we have no directory information. This is // a work in progress. std::string DirName = ""; - + if (!llvm::sys::Path(Entry->getName()).isAbsolute()) { llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory(); - DirName = P.toString() + "/"; + DirName = P.str() + "/"; } - - // Add the name of the file as an <h1> tag. - + + // Add the name of the file as an <h1> tag. + { std::string s; llvm::raw_string_ostream os(s); - + os << "<!-- REPORTHEADER -->\n" << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n" "<tr><td class=\"rowname\">File:</td><td>" << html::EscapeText(DirName) << html::EscapeText(Entry->getName()) << "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>" - "<a href=\"#EndPath\">line " + "<a href=\"#EndPath\">line " << (*D.rbegin()).getLocation().asLocation().getInstantiationLineNumber() << ", column " << (*D.rbegin()).getLocation().asLocation().getInstantiationColumnNumber() << "</a></td></tr>\n" "<tr><td class=\"rowname\">Description:</td><td>" << D.getDescription() << "</td></tr>\n"; - + // Output any other meta data. - + for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end(); I!=E; ++I) { os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n"; } - + os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n" - "<h3>Annotated Source Code</h3>\n"; - - R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str()); + "<h3>Annotated Source Code</h3>\n"; + + R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str()); } - + // Embed meta-data tags. - - const std::string& BugDesc = D.getDescription(); - - if (!BugDesc.empty()) { - std::string s; - llvm::raw_string_ostream os(s); - os << "\n<!-- BUGDESC " << BugDesc << " -->\n"; - R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str()); - } - - const std::string& BugType = D.getBugType(); - if (!BugType.empty()) { - std::string s; - llvm::raw_string_ostream os(s); - os << "\n<!-- BUGTYPE " << BugType << " -->\n"; - R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str()); - } - - const std::string& BugCategory = D.getCategory(); - - if (!BugCategory.empty()) { - std::string s; - llvm::raw_string_ostream os(s); - os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n"; - R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str()); - } - { std::string s; llvm::raw_string_ostream os(s); + + const std::string& BugDesc = D.getDescription(); + if (!BugDesc.empty()) + os << "\n<!-- BUGDESC " << BugDesc << " -->\n"; + + const std::string& BugType = D.getBugType(); + if (!BugType.empty()) + os << "\n<!-- BUGTYPE " << BugType << " -->\n"; + + const std::string& BugCategory = D.getCategory(); + if (!BugCategory.empty()) + os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n"; + os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n"; - R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str()); - } - - { - std::string s; - llvm::raw_string_ostream os(s); + os << "\n<!-- BUGLINE " << D.back()->getLocation().asLocation().getInstantiationLineNumber() << " -->\n"; - R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str()); - } - - { - std::string s; - llvm::raw_string_ostream os(s); + os << "\n<!-- BUGPATHLENGTH " << D.size() << " -->\n"; - R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str()); + + // Mark the end of the tags. + os << "\n<!-- BUGMETAEND -->\n"; + + // Insert the text. + R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str()); } // Add CSS, header, and footer. - + html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName()); - + // Get the rewrite buffer. const RewriteBuffer *Buf = R.getRewriteBufferFor(FID); - + if (!Buf) { - llvm::cerr << "warning: no diagnostics generated for main file.\n"; + llvm::errs() << "warning: no diagnostics generated for main file.\n"; return; } - // Create the stream to write out the HTML. - std::ofstream os; - - { - // Create a path for the target HTML file. - llvm::sys::Path F(FilePrefix); - F.makeUnique(false, NULL); - - // Rename the file with an HTML extension. - llvm::sys::Path H(F); - H.appendSuffix("html"); - F.renamePathOnDisk(H, NULL); - - os.open(H.toString().c_str()); - - if (!os) { - llvm::cerr << "warning: could not create file '" << F.toString() << "'\n"; - return; - } + // Create a path for the target HTML file. + llvm::sys::Path F(FilePrefix); + F.makeUnique(false, NULL); + + // Rename the file with an HTML extension. + llvm::sys::Path H(F); + H.appendSuffix("html"); + F.renamePathOnDisk(H, NULL); + + std::string ErrorMsg; + llvm::raw_fd_ostream os(H.c_str(), ErrorMsg); + + if (!ErrorMsg.empty()) { + (llvm::errs() << "warning: could not create file '" << F.str() + << "'\n").flush(); + return; } - - // Emit the HTML to disk. + if (FilesMade) + FilesMade->push_back(H.getLast()); + + // Emit the HTML to disk. for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I) os << *I; } @@ -328,24 +345,24 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) { void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, const PathDiagnosticPiece& P, unsigned num, unsigned max) { - + // For now, just draw a box above the line in question, and emit the // warning. FullSourceLoc Pos = P.getLocation().asLocation(); - + if (!Pos.isValid()) - return; - + return; + SourceManager &SM = R.getSourceMgr(); assert(&Pos.getManager() == &SM && "SourceManagers are different!"); std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedInstantiationLoc(Pos); - + if (LPosInfo.first != BugFileID) return; - + const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first); - const char* FileStart = Buf->getBufferStart(); - + const char* FileStart = Buf->getBufferStart(); + // Compute the column number. Rewind from the current position to the start // of the line. unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second); @@ -357,12 +374,12 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, const char* FileEnd = Buf->getBufferEnd(); while (*LineEnd != '\n' && LineEnd != FileEnd) ++LineEnd; - + // Compute the margin offset by counting tabs and non-tabs. - unsigned PosNo = 0; + unsigned PosNo = 0; for (const char* c = LineStart; c != TokInstantiationPtr; ++c) PosNo += *c == '\t' ? 8 : 1; - + // Create the html for the message. const char *Kind = 0; @@ -372,22 +389,22 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, // Setting Kind to "Control" is intentional. case PathDiagnosticPiece::Macro: Kind = "Control"; break; } - + std::string sbuf; llvm::raw_string_ostream os(sbuf); - + os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\""; - + if (num == max) os << "EndPath"; else os << "Path" << num; - + os << "\" class=\"msg"; if (Kind) - os << " msg" << Kind; + os << " msg" << Kind; os << "\" style=\"margin-left:" << PosNo << "ex"; - + // Output a maximum size. if (!isa<PathDiagnosticMacroPiece>(P)) { // Get the string and determining its maximum substring. @@ -395,32 +412,32 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, unsigned max_token = 0; unsigned cnt = 0; unsigned len = Msg.size(); - + for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I) switch (*I) { default: ++cnt; - continue; + continue; case ' ': case '\t': case '\n': if (cnt > max_token) max_token = cnt; cnt = 0; } - + if (cnt > max_token) max_token = cnt; - + // Determine the approximate size of the message bubble in em. unsigned em; const unsigned max_line = 120; - + if (max_token >= max_line) em = max_token / 2; else { unsigned characters = max_line; unsigned lines = len / max_line; - + if (lines > 0) { for (; characters > max_token; --characters) if (len / characters > lines) { @@ -428,18 +445,18 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, break; } } - + em = characters / 2; } - + if (em < max_line/2) - os << "; max-width:" << em << "em"; + os << "; max-width:" << em << "em"; } else os << "; max-width:100em"; - + os << "\">"; - + if (max > 1) { os << "<table class=\"msgT\"><tr><td valign=\"top\">"; os << "<div class=\"PathIndex"; @@ -449,10 +466,10 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, } if (const PathDiagnosticMacroPiece *MP = - dyn_cast<PathDiagnosticMacroPiece>(&P)) { + dyn_cast<PathDiagnosticMacroPiece>(&P)) { os << "Within the expansion of the macro '"; - + // Get the name of the macro by relexing it. { FullSourceLoc L = MP->getLocation().asLocation().getInstantiationLoc(); @@ -461,15 +478,15 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first; Lexer rawLexer(L, PP->getLangOptions(), BufferInfo.first, MacroName, BufferInfo.second); - + Token TheTok; rawLexer.LexFromRawLexer(TheTok); for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i) os << MacroName[i]; } - + os << "':\n"; - + if (max > 1) os << "</td></tr></table>"; @@ -478,21 +495,21 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, } else { os << html::EscapeText(P.getString()); - + if (max > 1) os << "</td></tr></table>"; } - + os << "</div></td></tr>"; // Insert the new html. - unsigned DisplayPos = LineEnd - FileStart; - SourceLocation Loc = + unsigned DisplayPos = LineEnd - FileStart; + SourceLocation Loc = SM.getLocForStartOfFile(LPosInfo.first).getFileLocWithOffset(DisplayPos); - R.InsertStrBefore(Loc, os.str()); + R.InsertTextBefore(Loc, os.str()); - // Now highlight the ranges. + // Now highlight the ranges. for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end(); I != E; ++I) HighlightRange(R, LPosInfo.first, *I); @@ -513,7 +530,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, std::string EscapedCode = html::EscapeText(Hint->CodeToInsert, true); EscapedCode = "<span class=\"CodeInsertionHint\">" + EscapedCode + "</span>"; - R.InsertStrBefore(Hint->InsertionLoc, EscapedCode); + R.InsertTextBefore(Hint->InsertionLoc, EscapedCode); } } #endif @@ -527,9 +544,9 @@ static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) { buf.push_back('a' + x); n = n / ('z' - 'a'); } while (n); - + assert(!buf.empty()); - + for (llvm::SmallVectorImpl<char>::reverse_iterator I=buf.rbegin(), E=buf.rend(); I!=E; ++I) os << *I; @@ -538,10 +555,10 @@ static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) { unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os, const PathDiagnosticMacroPiece& P, unsigned num) { - + for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end(); I!=E; ++I) { - + if (const PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I)) { num = ProcessMacroPiece(os, *MP, num); @@ -559,7 +576,7 @@ unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os, << "</td></tr></table></div>\n"; } } - + return num; } @@ -569,20 +586,20 @@ void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID, const char *HighlightEnd) { SourceManager &SM = R.getSourceMgr(); const LangOptions &LangOpts = R.getLangOpts(); - + SourceLocation InstantiationStart = SM.getInstantiationLoc(Range.getBegin()); unsigned StartLineNo = SM.getInstantiationLineNumber(InstantiationStart); - + SourceLocation InstantiationEnd = SM.getInstantiationLoc(Range.getEnd()); unsigned EndLineNo = SM.getInstantiationLineNumber(InstantiationEnd); - + if (EndLineNo < StartLineNo) return; - + if (SM.getFileID(InstantiationStart) != BugFileID || SM.getFileID(InstantiationEnd) != BugFileID) return; - + // Compute the column number of the end. unsigned EndColNo = SM.getInstantiationColumnNumber(InstantiationEnd); unsigned OldEndColNo = EndColNo; @@ -591,12 +608,12 @@ void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID, // Add in the length of the token, so that we cover multi-char tokens. EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM, LangOpts)-1; } - + // Highlight the range. Make the span tag the outermost tag for the // selected range. - + SourceLocation E = InstantiationEnd.getFileLocWithOffset(EndColNo - OldEndColNo); - + html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd); } diff --git a/lib/Frontend/HTMLPrint.cpp b/lib/Frontend/HTMLPrint.cpp index d5eb9fb5313d..8d93d70e83f4 100644 --- a/lib/Frontend/HTMLPrint.cpp +++ b/lib/Frontend/HTMLPrint.cpp @@ -21,12 +21,12 @@ #include "clang/Basic/FileManager.h" #include "clang/AST/ASTContext.h" #include "llvm/Support/MemoryBuffer.h" - +#include "llvm/Support/raw_ostream.h" using namespace clang; //===----------------------------------------------------------------------===// // Functional HTML pretty-printing. -//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// namespace { class HTMLPrinter : public ASTConsumer { @@ -40,7 +40,7 @@ namespace { PreprocessorFactory* ppf) : Out(OS), Diags(D), PP(pp), PPF(ppf) {} virtual ~HTMLPrinter(); - + void Initialize(ASTContext &context); }; } @@ -48,7 +48,7 @@ namespace { ASTConsumer* clang::CreateHTMLPrinter(llvm::raw_ostream *OS, Diagnostic &D, Preprocessor *PP, PreprocessorFactory* PPF) { - + return new HTMLPrinter(OS, D, PP, PPF); } @@ -78,7 +78,7 @@ HTMLPrinter::~HTMLPrinter() { // If we have a preprocessor, relex the file and syntax highlight. // We might not have a preprocessor if we come from a deserialized AST file, // for example. - + if (PP) html::SyntaxHighlight(R, FID, *PP); if (PPF) html::HighlightMacros(R, FID, *PP); html::EscapeText(R, FID, false, true); diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 8c80786210ff..822a5baf5972 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -17,21 +17,26 @@ #include "clang/Basic/LangOptions.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" #include "llvm/Config/config.h" #include <cstdio> -#include <vector> +#ifdef _MSC_VER + #define WIN32_LEAN_AND_MEAN 1 + #include <windows.h> +#endif using namespace clang; -void InitHeaderSearch::AddPath(const std::string &Path, IncludeDirGroup Group, - bool isCXXAware, bool isUserSupplied, - bool isFramework, bool IgnoreSysRoot) { +void InitHeaderSearch::AddPath(const llvm::StringRef &Path, + IncludeDirGroup Group, bool isCXXAware, + bool isUserSupplied, bool isFramework, + bool IgnoreSysRoot) { assert(!Path.empty() && "can't handle empty path here"); FileManager &FM = Headers.getFileMgr(); - + // Compute the actual path, taking into consideration -isysroot. llvm::SmallString<256> MappedPath; - + // Handle isysroot. if (Group == System && !IgnoreSysRoot) { // FIXME: Portability. This should be a sys::Path interface, this doesn't @@ -39,7 +44,7 @@ void InitHeaderSearch::AddPath(const std::string &Path, IncludeDirGroup Group, if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present. MappedPath.append(isysroot.begin(), isysroot.end()); } - + MappedPath.append(Path.begin(), Path.end()); // Compute the DirectoryLookup type. @@ -50,22 +55,19 @@ void InitHeaderSearch::AddPath(const std::string &Path, IncludeDirGroup Group, Type = SrcMgr::C_System; else Type = SrcMgr::C_ExternCSystem; - - + + // If the directory exists, add it. - if (const DirectoryEntry *DE = FM.getDirectory(&MappedPath[0], - &MappedPath[0]+ - MappedPath.size())) { + if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str())) { IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied, isFramework)); return; } - + // Check to see if this is an apple-style headermap (which are not allowed to // be frameworks). if (!isFramework) { - if (const FileEntry *FE = FM.getFile(&MappedPath[0], - &MappedPath[0]+MappedPath.size())) { + if (const FileEntry *FE = FM.getFile(MappedPath.str())) { if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) { // It is a headermap, add it to the search path. IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied)); @@ -73,10 +75,10 @@ void InitHeaderSearch::AddPath(const std::string &Path, IncludeDirGroup Group, } } } - + if (Verbose) - fprintf(stderr, "ignoring nonexistent directory \"%s\"\n", - MappedPath.c_str()); + llvm::errs() << "ignoring nonexistent directory \"" + << MappedPath.str() << "\"\n"; } @@ -90,8 +92,7 @@ void InitHeaderSearch::AddEnvVarPaths(const char *Name) { if (delim-at == 0) AddPath(".", Angled, false, true, false); else - AddPath(std::string(at, std::string::size_type(delim-at)), Angled, false, - true, false); + AddPath(llvm::StringRef(at, delim-at), Angled, false, true, false); at = delim + 1; delim = strchr(at, llvm::sys::PathSeparator); } @@ -101,104 +102,321 @@ void InitHeaderSearch::AddEnvVarPaths(const char *Name) { AddPath(at, Angled, false, true, false); } +void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base, + const char *Dir32, + const char *Dir64, + const llvm::Triple &triple) { + llvm::Triple::ArchType arch = triple.getArch(); + bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64; -void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang) { - // FIXME: temporary hack: hard-coded paths. - // FIXME: get these from the target? - -#ifdef LLVM_ON_WIN32 - if (Lang.CPlusPlus) { - // Mingw32 GCC version 4 - AddPath("c:/mingw/lib/gcc/mingw32/4.3.0/include/c++", - System, true, false, false); - AddPath("c:/mingw/lib/gcc/mingw32/4.3.0/include/c++/mingw32", - System, true, false, false); - AddPath("c:/mingw/lib/gcc/mingw32/4.3.0/include/c++/backward", - System, true, false, false); + AddPath(Base, System, true, false, false); + if (is64bit) + AddPath(Base + "/" + Dir64, System, true, false, false); + else + AddPath(Base + "/" + Dir32, System, true, false, false); + AddPath(Base + "/backward", System, true, false, false); +} + +void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base, + const char *Arch, + const char *Version) { + std::string localBase = Base + "/" + Arch + "/" + Version + "/include"; + AddPath(localBase, System, true, false, false); + AddPath(localBase + "/c++", System, true, false, false); + AddPath(localBase + "/c++/backward", System, true, false, false); +} + + // FIXME: This probably should goto to some platform utils place. +#ifdef _MSC_VER + // Read registry string. +bool getSystemRegistryString(const char *keyPath, const char *valueName, + char *value, size_t maxLength) { + HKEY hRootKey = NULL; + HKEY hKey = NULL; + const char* subKey = NULL; + DWORD valueType; + DWORD valueSize = maxLength - 1; + bool returnValue = false; + if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { + hRootKey = HKEY_CLASSES_ROOT; + subKey = keyPath + 18; } + else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { + hRootKey = HKEY_USERS; + subKey = keyPath + 11; + } + else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { + hRootKey = HKEY_LOCAL_MACHINE; + subKey = keyPath + 19; + } + else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { + hRootKey = HKEY_CURRENT_USER; + subKey = keyPath + 18; + } + else + return(false); + long lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey); + if (lResult == ERROR_SUCCESS) { + lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, + (LPBYTE)value, &valueSize); + if (lResult == ERROR_SUCCESS) + returnValue = true; + RegCloseKey(hKey); + } + return(returnValue); +} +#else // _MSC_VER + // Read registry string. +bool getSystemRegistryString(const char *, const char *, char *, size_t) { + return(false); +} +#endif // _MSC_VER + + // Get Visual Studio installation directory. +bool getVisualStudioDir(std::string &path) { + // Try the Windows registry first. + char vs80IDEInstallDir[256]; + char vs90IDEInstallDir[256]; + const char* vsIDEInstallDir = NULL; + bool has80 = getSystemRegistryString( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0", + "InstallDir", vs80IDEInstallDir, sizeof(vs80IDEInstallDir) - 1); + bool has90 = getSystemRegistryString( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0", + "InstallDir", vs90IDEInstallDir, sizeof(vs90IDEInstallDir) - 1); + // If we have both vc80 and vc90, pick version we were compiled with. + if (has80 && has90) { + #ifdef _MSC_VER + #if (_MSC_VER >= 1500) // VC90 + vsIDEInstallDir = vs90IDEInstallDir; + #elif (_MSC_VER == 1400) // VC80 + vsIDEInstallDir = vs80IDEInstallDir; + #else + vsIDEInstallDir = vs90IDEInstallDir; + #endif + #else + vsIDEInstallDir = vs90IDEInstallDir; + #endif + } + else if (has90) + vsIDEInstallDir = vs90IDEInstallDir; + else if (has80) + vsIDEInstallDir = vs80IDEInstallDir; + if (vsIDEInstallDir && *vsIDEInstallDir) { + char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); + if (p) + *p = '\0'; + path = vsIDEInstallDir; + return(true); + } + else { + // Try the environment. + const char* vs90comntools = getenv("VS90COMNTOOLS"); + const char* vs80comntools = getenv("VS80COMNTOOLS"); + const char* vscomntools = NULL; + // If we have both vc80 and vc90, pick version we were compiled with. + if (vs90comntools && vs80comntools) { + #if (_MSC_VER >= 1500) // VC90 + vscomntools = vs90comntools; + #elif (_MSC_VER == 1400) // VC80 + vscomntools = vs80comntools; + #else + vscomntools = vs90comntools; + #endif + } + else if (vs90comntools) + vscomntools = vs90comntools; + else if (vs80comntools) + vscomntools = vs80comntools; + if (vscomntools && *vscomntools) { + char *p = (char*)strstr(vscomntools, "\\Common7\\Tools"); + if (p) + *p = '\0'; + path = vscomntools; + return(true); + } + else + return(false); + } + return(false); +} - // Mingw32 GCC version 4 - AddPath("C:/mingw/include", System, false, false, false); -#else - - if (Lang.CPlusPlus) { - AddPath("/usr/include/c++/4.2.1", System, true, false, false); - AddPath("/usr/include/c++/4.2.1/i686-apple-darwin10", System, true, false, - false); - AddPath("/usr/include/c++/4.2.1/backward", System, true, false, false); - - AddPath("/usr/include/c++/4.0.0", System, true, false, false); - AddPath("/usr/include/c++/4.0.0/i686-apple-darwin8", System, true, false, - false); - AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false); - - // Ubuntu 7.10 - Gutsy Gibbon - AddPath("/usr/include/c++/4.1.3", System, true, false, false); - AddPath("/usr/include/c++/4.1.3/i486-linux-gnu", System, true, false, - false); - AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false); - - // Ubuntu 9.04 - AddPath("/usr/include/c++/4.3.3", System, true, false, false); - AddPath("/usr/include/c++/4.3.3/x86_64-linux-gnu/", System, true, false, - false); - AddPath("/usr/include/c++/4.3.3/backward", System, true, false, false); - - // Fedora 8 - AddPath("/usr/include/c++/4.1.2", System, true, false, false); - AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false, - false); - AddPath("/usr/include/c++/4.1.2/backward", System, true, false, false); - - // Fedora 9 - AddPath("/usr/include/c++/4.3.0", System, true, false, false); - AddPath("/usr/include/c++/4.3.0/i386-redhat-linux", System, true, false, - false); - AddPath("/usr/include/c++/4.3.0/backward", System, true, false, false); - - // Fedora 10 - AddPath("/usr/include/c++/4.3.2", System, true, false, false); - AddPath("/usr/include/c++/4.3.2/i386-redhat-linux", System, true, false, - false); - AddPath("/usr/include/c++/4.3.2/backward", System, true, false, false); - - // Arch Linux 2008-06-24 - AddPath("/usr/include/c++/4.3.1", System, true, false, false); - AddPath("/usr/include/c++/4.3.1/i686-pc-linux-gnu", System, true, false, - false); - AddPath("/usr/include/c++/4.3.1/backward", System, true, false, false); - AddPath("/usr/include/c++/4.3.1/x86_64-unknown-linux-gnu", System, true, - false, false); - - // Gentoo x86 stable - AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4", System, - true, false, false); - AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/" - "i686-pc-linux-gnu", System, true, false, false); - AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/backward", - System, true, false, false); - - // Gentoo amd64 stable - AddPath("/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", System, - true, false, false); - AddPath("/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/" - "i686-pc-linux-gnu", System, true, false, false); - AddPath("/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/backward", - System, true, false, false); - - // DragonFly - AddPath("/usr/include/c++/4.1", System, true, false, false); - - // FreeBSD - AddPath("/usr/include/c++/4.2", System, true, false, false); +void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, + const llvm::Triple &triple) { + // FIXME: temporary hack: hard-coded paths. + llvm::Triple::OSType os = triple.getOS(); + + switch (os) { + case llvm::Triple::Win32: + { + std::string VSDir; + if (getVisualStudioDir(VSDir)) { + AddPath(VSDir + "\\VC\\include", System, false, false, false); + AddPath(VSDir + "\\VC\\PlatformSDK\\Include", + System, false, false, false); + } + else { + // Default install paths. + AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include", + System, false, false, false); + AddPath( + "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", + System, false, false, false); + AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include", + System, false, false, false); + AddPath( + "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include", + System, false, false, false); + // For some clang developers. + AddPath("G:/Program Files/Microsoft Visual Studio 9.0/VC/include", + System, false, false, false); + AddPath( + "G:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", + System, false, false, false); + } + } + break; + case llvm::Triple::Cygwin: + if (Lang.CPlusPlus) { + AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include", + System, false, false, false); + AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++", + System, false, false, false); + } + AddPath("/usr/include", System, false, false, false); + break; + case llvm::Triple::MinGW64: + if (Lang.CPlusPlus) { // I'm guessing here. + // Try gcc 4.4.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0"); + // Try gcc 4.3.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0"); + } + // Fall through. + case llvm::Triple::MinGW32: + if (Lang.CPlusPlus) { + // Try gcc 4.4.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0"); + // Try gcc 4.3.0 + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0"); + } + AddPath("c:/mingw/include", System, true, false, false); + break; + default: + if (Lang.CPlusPlus) { + switch (os) { + case llvm::Triple::Darwin: + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "i686-apple-darwin10", + "i686-apple-darwin10/x86_64", + triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", + "i686-apple-darwin8", + "i686-apple-darwin8", + triple); + break; + case llvm::Triple::Linux: + // Ubuntu 7.10 - Gutsy Gibbon + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3", + "i486-linux-gnu", + "i486-linux-gnu", + triple); + // Ubuntu 9.04 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3", + "x86_64-linux-gnu/32", + "x86_64-linux-gnu", + triple); + // Fedora 8 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2", + "i386-redhat-linux", + "i386-redhat-linux", + triple); + // Fedora 9 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0", + "i386-redhat-linux", + "i386-redhat-linux", + triple); + // Fedora 10 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2", + "i386-redhat-linux", + "i386-redhat-linux", + triple); + // openSUSE 11.1 32 bit + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", + "i586-suse-linux", + "i586-suse-linux", + triple); + // openSUSE 11.1 64 bit + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", + "x86_64-suse-linux/32", + "x86_64-suse-linux", + triple); + // openSUSE 11.2 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4", + "i586-suse-linux", + "i586-suse-linux", + triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4", + "x86_64-suse-linux", + "x86_64-suse-linux", + triple); + // Arch Linux 2008-06-24 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1", + "i686-pc-linux-gnu", + "i686-pc-linux-gnu", + triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-gnu", + triple); + // Gentoo x86 2009.0 stable + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4", + "i686-pc-linux-gnu", + "i686-pc-linux-gnu", + triple); + // Gentoo x86 2008.0 stable + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4", + "i686-pc-linux-gnu", + "i686-pc-linux-gnu", + triple); + // Ubuntu 8.10 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", + "i486-pc-linux-gnu", + "i486-pc-linux-gnu", + triple); + // Gentoo amd64 stable + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", + "i686-pc-linux-gnu", + "i686-pc-linux-gnu", + triple); + break; + case llvm::Triple::FreeBSD: + // DragonFly + AddPath("/usr/include/c++/4.1", System, true, false, false); + // FreeBSD + AddPath("/usr/include/c++/4.2", System, true, false, false); + break; + case llvm::Triple::Solaris: + // AuroraUX + AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4", + "i386-pc-solaris2.11", + "i386-pc-solaris2.11", + triple); + break; + default: + break; + } + } + break; } AddPath("/usr/local/include", System, false, false, false); - AddPath("/usr/include", System, false, false, false); AddPath("/System/Library/Frameworks", System, true, false, true); AddPath("/Library/Frameworks", System, true, false, true); -#endif } void InitHeaderSearch::AddDefaultEnvVarPaths(const LangOptions &Lang) { @@ -223,9 +441,9 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps; for (unsigned i = 0; i != SearchList.size(); ++i) { unsigned DirToRemove = i; - + const DirectoryLookup &CurEntry = SearchList[i]; - + if (CurEntry.isNormalDir()) { // If this isn't the first time we've seen this dir, remove it. if (SeenDirs.insert(CurEntry.getDir())) @@ -240,7 +458,7 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, if (SeenHeaderMaps.insert(CurEntry.getHeaderMap())) continue; } - + // If we have a normal #include dir/framework/headermap that is shadowed // later in the chain by a system include location, we actually want to // ignore the user's request and drop the user dir... keeping the system @@ -253,13 +471,13 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, unsigned FirstDir; for (FirstDir = 0; ; ++FirstDir) { assert(FirstDir != i && "Didn't find dupe?"); - + const DirectoryLookup &SearchEntry = SearchList[FirstDir]; // If these are different lookup types, then they can't be the dupe. if (SearchEntry.getLookupType() != CurEntry.getLookupType()) continue; - + bool isSame; if (CurEntry.isNormalDir()) isSame = SearchEntry.getDir() == CurEntry.getDir(); @@ -269,11 +487,11 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?"); isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap(); } - + if (isSame) break; } - + // If the first dir in the search path is a non-system dir, zap it // instead of the system one. if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User) @@ -287,7 +505,7 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, fprintf(stderr, " as it is a non-system directory that duplicates" " a system directory\n"); } - + // This is reached if the current entry is a duplicate. Remove the // DirToRemove (usually the current dir). SearchList.erase(SearchList.begin()+DirToRemove); @@ -306,11 +524,11 @@ void InitHeaderSearch::Realize() { IncludeGroup[After].end()); RemoveDuplicates(SearchList, Verbose); RemoveDuplicates(IncludeGroup[Quoted], Verbose); - + // Prepend QUOTED list on the search list. - SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(), + SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(), IncludeGroup[Quoted].end()); - + bool DontSearchCurDir = false; // TODO: set to true if -I- is set? Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(), @@ -338,4 +556,3 @@ void InitHeaderSearch::Realize() { fprintf(stderr, "End of search list.\n"); } } - diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index e41dfdda07e9..0f3b4b8236be 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -30,7 +30,7 @@ static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro) { // Turn the = into ' '. Buf.insert(Buf.end(), Macro, Equal); Buf.push_back(' '); - + // Per GCC -D semantics, the macro ends at \n if it exists. const char *End = strpbrk(Equal, "\n\r"); if (End) { @@ -40,7 +40,7 @@ static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro) { } else { End = Equal+strlen(Equal); } - + Buf.insert(Buf.end(), Equal+1, End); } else { // Push "macroname 1". @@ -62,7 +62,7 @@ static void UndefineBuiltinMacro(std::vector<char> &Buf, const char *Macro) { } /// Add the quoted name of an implicit include file. -static void AddQuotedIncludePath(std::vector<char> &Buf, +static void AddQuotedIncludePath(std::vector<char> &Buf, const std::string &File) { // Implicit include paths should be resolved relative to the current // working directory first, and then use the regular header search @@ -75,17 +75,17 @@ static void AddQuotedIncludePath(std::vector<char> &Buf, Path.makeAbsolute(); if (!Path.exists()) Path = File; - + // Escape double quotes etc. Buf.push_back('"'); - std::string EscapedFile = Lexer::Stringify(Path.toString()); + std::string EscapedFile = Lexer::Stringify(Path.str()); Buf.insert(Buf.end(), EscapedFile.begin(), EscapedFile.end()); Buf.push_back('"'); } /// AddImplicitInclude - Add an implicit #include of the specified file to the /// predefines buffer. -static void AddImplicitInclude(std::vector<char> &Buf, +static void AddImplicitInclude(std::vector<char> &Buf, const std::string &File) { const char *Inc = "#include "; Buf.insert(Buf.end(), Inc, Inc+strlen(Inc)); @@ -106,12 +106,12 @@ static void AddImplicitIncludeMacros(std::vector<char> &Buf, /// AddImplicitIncludePTH - Add an implicit #include using the original file /// used to generate a PTH cache. -static void AddImplicitIncludePTH(std::vector<char> &Buf, Preprocessor &PP, +static void AddImplicitIncludePTH(std::vector<char> &Buf, Preprocessor &PP, const std::string& ImplicitIncludePTH) { PTHManager *P = PP.getPTHManager(); assert(P && "No PTHManager."); const char *OriginalFile = P->getOriginalSourceFile(); - + if (!OriginalFile) { assert(!ImplicitIncludePTH.empty()); fprintf(stderr, "error: PTH file '%s' does not designate an original " @@ -119,7 +119,7 @@ static void AddImplicitIncludePTH(std::vector<char> &Buf, Preprocessor &PP, ImplicitIncludePTH.c_str()); exit (1); } - + AddImplicitInclude(Buf, OriginalFile); } @@ -144,7 +144,7 @@ static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal, static void DefineFloatMacros(std::vector<char> &Buf, const char *Prefix, const llvm::fltSemantics *Sem) { const char *DenormMin, *Epsilon, *Max, *Min; - DenormMin = PickFP(Sem, "1.40129846e-45F", "4.9406564584124654e-324", + DenormMin = PickFP(Sem, "1.40129846e-45F", "4.9406564584124654e-324", "3.64519953188247460253e-4951L", "4.94065645841246544176568792868221e-324L", "6.47517511943802511092443895822764655e-4966L"); @@ -167,7 +167,7 @@ static void DefineFloatMacros(std::vector<char> &Buf, const char *Prefix, "1.18973149535723176502e+4932L", "1.79769313486231580793728971405301e+308L", "1.18973149535723176508575932662800702e+4932L"); - + char MacroBuf[100]; sprintf(MacroBuf, "__%s_DENORM_MIN__=%s", Prefix, DenormMin); DefineBuiltinMacro(Buf, MacroBuf); @@ -210,8 +210,10 @@ static void DefineTypeSize(const char *MacroName, unsigned TypeWidth, MaxVal = (1LL << (TypeWidth - 1)) - 1; else MaxVal = ~0LL >> (64-TypeWidth); - - sprintf(MacroBuf, "%s=%llu%s", MacroName, MaxVal, ValSuffix); + + // FIXME: Switch to using raw_ostream and avoid utostr(). + sprintf(MacroBuf, "%s=%s%s", MacroName, llvm::utostr(MaxVal).c_str(), + ValSuffix); DefineBuiltinMacro(Buf, MacroBuf); } @@ -230,32 +232,35 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // Compiler version introspection macros. DefineBuiltinMacro(Buf, "__llvm__=1"); // LLVM Backend DefineBuiltinMacro(Buf, "__clang__=1"); // Clang Frontend - + // Currently claim to be compatible with GCC 4.2.1-5621. DefineBuiltinMacro(Buf, "__GNUC_MINOR__=2"); DefineBuiltinMacro(Buf, "__GNUC_PATCHLEVEL__=1"); DefineBuiltinMacro(Buf, "__GNUC__=4"); DefineBuiltinMacro(Buf, "__GXX_ABI_VERSION=1002"); DefineBuiltinMacro(Buf, "__VERSION__=\"4.2.1 Compatible Clang Compiler\""); - - + + // Initialize language-specific preprocessor defines. - + // These should all be defined in the preprocessor according to the // current language configuration. if (!LangOpts.Microsoft) DefineBuiltinMacro(Buf, "__STDC__=1"); if (LangOpts.AsmPreprocessor) DefineBuiltinMacro(Buf, "__ASSEMBLER__=1"); - if (LangOpts.C99 && !LangOpts.CPlusPlus) - DefineBuiltinMacro(Buf, "__STDC_VERSION__=199901L"); - else if (0) // STDC94 ? - DefineBuiltinMacro(Buf, "__STDC_VERSION__=199409L"); + + if (!LangOpts.CPlusPlus) { + if (LangOpts.C99) + DefineBuiltinMacro(Buf, "__STDC_VERSION__=199901L"); + else if (!LangOpts.GNUMode && LangOpts.Digraphs) + DefineBuiltinMacro(Buf, "__STDC_VERSION__=199409L"); + } // Standard conforming mode? if (!LangOpts.GNUMode) DefineBuiltinMacro(Buf, "__STRICT_ANSI__=1"); - + if (LangOpts.CPlusPlus0x) DefineBuiltinMacro(Buf, "__GXX_EXPERIMENTAL_CXX0X__"); @@ -263,32 +268,28 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineBuiltinMacro(Buf, "__STDC_HOSTED__=0"); else DefineBuiltinMacro(Buf, "__STDC_HOSTED__=1"); - + if (LangOpts.ObjC1) { DefineBuiltinMacro(Buf, "__OBJC__=1"); if (LangOpts.ObjCNonFragileABI) { DefineBuiltinMacro(Buf, "__OBJC2__=1"); DefineBuiltinMacro(Buf, "OBJC_ZEROCOST_EXCEPTIONS=1"); - DefineBuiltinMacro(Buf, "__EXCEPTIONS=1"); } if (LangOpts.getGCMode() != LangOptions::NonGC) DefineBuiltinMacro(Buf, "__OBJC_GC__=1"); - + if (LangOpts.NeXTRuntime) DefineBuiltinMacro(Buf, "__NEXT_RUNTIME__=1"); } - + // darwin_constant_cfstrings controls this. This is also dependent // on other things like the runtime I believe. This is set even for C code. DefineBuiltinMacro(Buf, "__CONSTANT_CFSTRINGS__=1"); - + if (LangOpts.ObjC2) DefineBuiltinMacro(Buf, "OBJC_NEW_PROPERTIES"); - if (LangOpts.ObjCSenderDispatch) - DefineBuiltinMacro(Buf, "__OBJC_SENDER_AWARE_DISPATCH__"); - if (LangOpts.PascalStrings) DefineBuiltinMacro(Buf, "__PASCAL_STRINGS__"); @@ -296,32 +297,42 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineBuiltinMacro(Buf, "__block=__attribute__((__blocks__(byref)))"); DefineBuiltinMacro(Buf, "__BLOCKS__=1"); } - + + if (LangOpts.Exceptions) + DefineBuiltinMacro(Buf, "__EXCEPTIONS=1"); + if (LangOpts.CPlusPlus) { DefineBuiltinMacro(Buf, "__DEPRECATED=1"); - DefineBuiltinMacro(Buf, "__EXCEPTIONS=1"); DefineBuiltinMacro(Buf, "__GNUG__=4"); DefineBuiltinMacro(Buf, "__GXX_WEAK__=1"); - DefineBuiltinMacro(Buf, "__cplusplus=1"); + if (LangOpts.GNUMode) + DefineBuiltinMacro(Buf, "__cplusplus=1"); + else + // C++ [cpp.predefined]p1: + // The name_ _cplusplusis defined to the value199711Lwhen compiling a + // C++ translation unit. + DefineBuiltinMacro(Buf, "__cplusplus=199711L"); DefineBuiltinMacro(Buf, "__private_extern__=extern"); + // Ugly hack to work with GNU libstdc++. + DefineBuiltinMacro(Buf, "_GNU_SOURCE=1"); } - + // Filter out some microsoft extensions when trying to parse in ms-compat - // mode. + // mode. if (LangOpts.Microsoft) { DefineBuiltinMacro(Buf, "__int8=__INT8_TYPE__"); DefineBuiltinMacro(Buf, "__int16=__INT16_TYPE__"); DefineBuiltinMacro(Buf, "__int32=__INT32_TYPE__"); DefineBuiltinMacro(Buf, "__int64=__INT64_TYPE__"); } - + if (LangOpts.Optimize) DefineBuiltinMacro(Buf, "__OPTIMIZE__=1"); if (LangOpts.OptimizeSize) DefineBuiltinMacro(Buf, "__OPTIMIZE_SIZE__=1"); - + // Initialize target-specific preprocessor defines. - + // Define type sizing macros based on the target properties. assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far"); DefineBuiltinMacro(Buf, "__CHAR_BIT__=8"); @@ -339,7 +350,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, IntMaxWidth = TI.getIntWidth(); IntMaxSuffix = ""; } - + DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Buf); DefineTypeSize("__SHRT_MAX__", TI.getShortWidth(), "", true, Buf); DefineTypeSize("__INT_MAX__", TI.getIntWidth(), "", true, Buf); @@ -356,7 +367,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineType("__WCHAR_TYPE__", TI.getWCharType(), Buf); // FIXME: TargetInfo hookize __WINT_TYPE__. DefineBuiltinMacro(Buf, "__WINT_TYPE__=int"); - + DefineFloatMacros(Buf, "FLT", &TI.getFloatFormat()); DefineFloatMacros(Buf, "DBL", &TI.getDoubleFormat()); DefineFloatMacros(Buf, "LDBL", &TI.getLongDoubleFormat()); @@ -364,39 +375,39 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // Define a __POINTER_WIDTH__ macro for stdint.h. sprintf(MacroBuf, "__POINTER_WIDTH__=%d", (int)TI.getPointerWidth(0)); DefineBuiltinMacro(Buf, MacroBuf); - + if (!LangOpts.CharIsSigned) - DefineBuiltinMacro(Buf, "__CHAR_UNSIGNED__"); + DefineBuiltinMacro(Buf, "__CHAR_UNSIGNED__"); // Define fixed-sized integer types for stdint.h assert(TI.getCharWidth() == 8 && "unsupported target types"); assert(TI.getShortWidth() == 16 && "unsupported target types"); DefineBuiltinMacro(Buf, "__INT8_TYPE__=char"); DefineBuiltinMacro(Buf, "__INT16_TYPE__=short"); - + if (TI.getIntWidth() == 32) DefineBuiltinMacro(Buf, "__INT32_TYPE__=int"); else { assert(TI.getLongLongWidth() == 32 && "unsupported target types"); DefineBuiltinMacro(Buf, "__INT32_TYPE__=long long"); } - + // 16-bit targets doesn't necessarily have a 64-bit type. if (TI.getLongLongWidth() == 64) DefineType("__INT64_TYPE__", TI.getInt64Type(), Buf); - + // Add __builtin_va_list typedef. { const char *VAList = TI.getVAListDeclaration(); Buf.insert(Buf.end(), VAList, VAList+strlen(VAList)); Buf.push_back('\n'); } - + if (const char *Prefix = TI.getUserLabelPrefix()) { sprintf(MacroBuf, "__USER_LABEL_PREFIX__=%s", Prefix); DefineBuiltinMacro(Buf, MacroBuf); } - + // Build configuration options. FIXME: these should be controlled by // command line options or something. DefineBuiltinMacro(Buf, "__FINITE_MATH_ONLY__=0"); @@ -439,15 +450,15 @@ static void InitializePredefinedMacros(const TargetInfo &TI, bool InitializePreprocessor(Preprocessor &PP, const PreprocessorInitOptions& InitOpts) { std::vector<char> PredefineBuffer; - + const char *LineDirective = "# 1 \"<built-in>\" 3\n"; PredefineBuffer.insert(PredefineBuffer.end(), LineDirective, LineDirective+strlen(LineDirective)); - + // Install things like __POWERPC__, __GNUC__, etc into the macro table. InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(), PredefineBuffer); - + // Add on the predefines from the driver. Wrap in a #line directive to report // that they come from the command line. LineDirective = "# 1 \"<command line>\" 1\n"; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 95b166159e7d..e61668dd3177 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -26,6 +26,7 @@ #include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Version.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" @@ -69,20 +70,21 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); PARSE_LANGOPT_BENIGN(PascalStrings); PARSE_LANGOPT_BENIGN(WritableStrings); - PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, + 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(NeXTRuntime, diag::warn_pch_objc_runtime); PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins); - PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, + PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, diag::warn_pch_thread_safe_statics); + PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads); PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks); PARSE_LANGOPT_BENIGN(EmitAllDecls); PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno); PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking); - PARSE_LANGOPT_IMPORTANT(HeinousExtensions, + PARSE_LANGOPT_IMPORTANT(HeinousExtensions, diag::warn_pch_heinous_extensions); // FIXME: Most of the options below are benign if the macro wasn't // used. Unfortunately, this means that a PCH compiled without @@ -100,13 +102,16 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control); PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed); if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) { - Reader.Diag(diag::warn_pch_gc_mode) + Reader.Diag(diag::warn_pch_gc_mode) << LangOpts.getGCMode() << PPLangOpts.getGCMode(); return true; } PARSE_LANGOPT_BENIGN(getVisibilityMode()); + PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(), + diag::warn_pch_stack_protector); PARSE_LANGOPT_BENIGN(InstantiationDepth); PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl); + PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors); #undef PARSE_LANGOPT_IRRELEVANT #undef PARSE_LANGOPT_BENIGN @@ -114,9 +119,9 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { } bool PCHValidator::ReadTargetTriple(const std::string &Triple) { - if (Triple != PP.getTargetInfo().getTargetTriple()) { + if (Triple != PP.getTargetInfo().getTriple().getTriple()) { Reader.Diag(diag::warn_pch_target_triple) - << Triple << PP.getTargetInfo().getTargetTriple(); + << Triple << PP.getTargetInfo().getTriple().getTriple(); return true; } return false; @@ -163,7 +168,7 @@ static inline bool startsWith(const std::string &Haystack, return startsWith(Haystack, Needle.c_str()); } -bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, +bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, unsigned PCHPredefLen, FileID PCHBufferID, std::string &SuggestedPredefines) { @@ -171,19 +176,19 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, unsigned PredefLen = PP.getPredefines().size(); // If the two predefines buffers compare equal, we're done! - if (PredefLen == PCHPredefLen && + if (PredefLen == PCHPredefLen && strncmp(Predef, PCHPredef, PCHPredefLen) == 0) return false; SourceManager &SourceMgr = PP.getSourceManager(); - + // The predefines buffers are different. Determine what the // differences are, and whether they require us to reject the PCH // file. std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen); std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen); - // Sort both sets of predefined buffer lines, since + // Sort both sets of predefined buffer lines, since std::sort(CmdLineLines.begin(), CmdLineLines.end()); std::sort(PCHLines.begin(), PCHLines.end()); @@ -202,11 +207,11 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, Reader.Diag(diag::warn_pch_compiler_options_mismatch); return true; } - + // This is a macro definition. Determine the name of the macro // we're defining. std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName + std::string::size_type EndOfMacroName = Missing.find_first_of("( \n\r", StartOfMacroName); assert(EndOfMacroName != std::string::npos && "Couldn't find the end of the macro name"); @@ -224,19 +229,19 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, if (!startsWith(*ConflictPos, MacroDefStart)) { // Different macro; we're done. ConflictPos = CmdLineLines.end(); - break; + break; } - - assert(ConflictPos->size() > MacroDefLen && + + assert(ConflictPos->size() > MacroDefLen && "Invalid #define in predefines buffer?"); - if ((*ConflictPos)[MacroDefLen] != ' ' && + if ((*ConflictPos)[MacroDefLen] != ' ' && (*ConflictPos)[MacroDefLen] != '(') continue; // Longer macro name; keep trying. - + // We found a conflicting macro definition. break; } - + if (ConflictPos != CmdLineLines.end()) { Reader.Diag(diag::warn_cmdline_conflicting_macro_def) << MacroName; @@ -253,13 +258,13 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, ConflictingDefines = true; continue; } - + // If the macro doesn't conflict, then we'll just pick up the // macro definition from the PCH file. Warn the user that they // made a mistake. if (ConflictingDefines) continue; // Don't complain if there are already conflicting defs - + if (!MissingDefines) { Reader.Diag(diag::warn_cmdline_missing_macro_defs); MissingDefines = true; @@ -273,10 +278,10 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, .getFileLocWithOffset(Offset); Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch); } - + if (ConflictingDefines) return true; - + // Determine what predefines were introduced based on command-line // parameters that were not present when building the PCH // file. Extra #defines are okay, so long as the identifiers being @@ -284,7 +289,7 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, std::vector<std::string> ExtraPredefines; std::set_difference(CmdLineLines.begin(), CmdLineLines.end(), PCHLines.begin(), PCHLines.end(), - std::back_inserter(ExtraPredefines)); + std::back_inserter(ExtraPredefines)); for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) { const std::string &Extra = ExtraPredefines[I]; if (!startsWith(Extra, "#define ") != 0) { @@ -295,7 +300,7 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef, // This is an extra macro definition. Determine the name of the // macro we're defining. std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName + std::string::size_type EndOfMacroName = Extra.find_first_of("( \n\r", StartOfMacroName); assert(EndOfMacroName != std::string::npos && "Couldn't find the end of the macro name"); @@ -336,7 +341,8 @@ void PCHValidator::ReadCounter(unsigned Value) { // PCH reader implementation //===----------------------------------------------------------------------===// -PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context) +PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, + const char *isysroot) : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), Consumer(0), @@ -344,24 +350,31 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context) IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), Comments(0), NumComments(0), - NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), NumStatementsRead(0), + TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot), + NumStatHits(0), NumStatMisses(0), + NumSLocEntriesRead(0), NumStatementsRead(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), - NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { } + NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), + CurrentlyLoadingTypeOrDecl(0) { + RelocatablePCH = false; +} PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags) + Diagnostic &Diags, const char *isysroot) : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), NumStatementsRead(0), + TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot), + NumStatHits(0), NumStatMisses(0), + NumSLocEntriesRead(0), NumStatementsRead(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), - NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { } + NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), + CurrentlyLoadingTypeOrDecl(0) { + RelocatablePCH = false; +} PCHReader::~PCHReader() {} @@ -385,12 +398,12 @@ public: typedef external_key_type internal_key_type; explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { } - + static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { return a == b; } - + static unsigned ComputeHash(Selector Sel) { unsigned N = Sel.getNumArgs(); if (N == 0) @@ -401,11 +414,11 @@ public: R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R); return R; } - + // This hopefully will just get inlined and removed by the optimizer. static const internal_key_type& GetInternalKey(const external_key_type& x) { return x; } - + static std::pair<unsigned, unsigned> ReadKeyDataLength(const unsigned char*& d) { using namespace clang::io; @@ -413,12 +426,12 @@ public: unsigned DataLen = ReadUnalignedLE16(d); return std::make_pair(KeyLen, DataLen); } - + internal_key_type ReadKey(const unsigned char* d, unsigned) { using namespace clang::io; SelectorTable &SelTable = Reader.getContext()->Selectors; unsigned N = ReadUnalignedLE16(d); - IdentifierInfo *FirstII + IdentifierInfo *FirstII = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); if (N == 0) return SelTable.getNullarySelector(FirstII); @@ -432,7 +445,7 @@ public: return SelTable.getSelector(N, Args.data()); } - + data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) { using namespace clang::io; unsigned NumInstanceMethods = ReadUnalignedLE16(d); @@ -443,7 +456,7 @@ public: // Load instance methods ObjCMethodList *Prev = 0; for (unsigned I = 0; I != NumInstanceMethods; ++I) { - ObjCMethodDecl *Method + ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); if (!Result.first.Method) { // This is the first method, which is the easy case. @@ -459,7 +472,7 @@ public: // Load factory methods Prev = 0; for (unsigned I = 0; I != NumFactoryMethods; ++I) { - ObjCMethodDecl *Method + ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); if (!Result.second.Method) { // This is the first method, which is the easy case. @@ -475,11 +488,11 @@ public: return Result; } }; - -} // end anonymous namespace + +} // end anonymous namespace /// \brief The on-disk hash table used for the global method pool. -typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait> +typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait> PCHMethodPoolLookupTable; namespace { @@ -498,23 +511,23 @@ public: typedef external_key_type internal_key_type; - explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0) + explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0) : Reader(Reader), KnownII(II) { } - + static bool EqualKey(const internal_key_type& a, const internal_key_type& b) { return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0 : false; } - + static unsigned ComputeHash(const internal_key_type& a) { return BernsteinHash(a.first, a.second); } - + // This hopefully will just get inlined and removed by the optimizer. static const internal_key_type& GetInternalKey(const external_key_type& x) { return x; } - + static std::pair<unsigned, unsigned> ReadKeyDataLength(const unsigned char*& d) { using namespace clang::io; @@ -522,14 +535,14 @@ public: unsigned KeyLen = ReadUnalignedLE16(d); return std::make_pair(KeyLen, DataLen); } - + static std::pair<const char*, unsigned> ReadKey(const unsigned char* d, unsigned n) { assert(n >= 2 && d[n-1] == '\0'); return std::make_pair((const char*) d, n-1); } - - IdentifierInfo *ReadData(const internal_key_type& k, + + IdentifierInfo *ReadData(const internal_key_type& k, const unsigned char* d, unsigned DataLen) { using namespace clang::io; @@ -561,7 +574,7 @@ public: Bits >>= 1; unsigned ObjCOrBuiltinID = Bits & 0x3FF; Bits >>= 10; - + assert(Bits == 0 && "Extra bits in the identifier?"); DataLen -= 6; @@ -576,7 +589,7 @@ public: // Set or check the various bits in the IdentifierInfo structure. // FIXME: Load token IDs lazily, too? II->setObjCOrBuiltinID(ObjCOrBuiltinID); - assert(II->isExtensionToken() == ExtensionToken && + assert(II->isExtensionToken() == ExtensionToken && "Incorrect extension token flag"); (void)ExtensionToken; II->setIsPoisoned(Poisoned); @@ -594,38 +607,25 @@ public: // Read all of the declarations visible at global scope with this // name. - Sema *SemaObj = Reader.getSema(); if (Reader.getContext() == 0) return II; - - while (DataLen > 0) { - NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (SemaObj) { - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D)); - SemaObj->IdResolver.AddDeclToIdentifierChain(II, D); - } else { - // Queue this declaration so that it will be added to the - // translation unit scope and identifier's declaration chain - // once a Sema object is known. - Reader.PreloadedDecls.push_back(D); - } - - DataLen -= 4; + if (DataLen > 0) { + llvm::SmallVector<uint32_t, 4> DeclIDs; + for (; DataLen > 0; DataLen -= 4) + DeclIDs.push_back(ReadUnalignedLE32(d)); + Reader.SetGloballyVisibleDecls(II, DeclIDs); } + return II; } }; - -} // end anonymous namespace + +} // end anonymous namespace /// \brief The on-disk hash table used to contain information about /// all of the identifiers in the program. -typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait> +typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait> PCHIdentifierLookupTable; -// FIXME: use the diagnostics machinery bool PCHReader::Error(const char *Msg) { unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg); Diag(DiagID); @@ -649,7 +649,7 @@ bool PCHReader::Error(const char *Msg) { /// /// \returns true if there was a mismatch (in which case the PCH file /// should be ignored), or false otherwise. -bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef, +bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef, unsigned PCHPredefLen, FileID PCHBufferID) { if (Listener) @@ -664,8 +664,7 @@ bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef, /// \brief Read the line table in the source manager block. /// \returns true if ther was an error. -static bool ParseLineTable(SourceManager &SourceMgr, - llvm::SmallVectorImpl<uint64_t> &Record) { +bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) { unsigned Idx = 0; LineTableInfo &LineTable = SourceMgr.getLineTable(); @@ -676,7 +675,8 @@ static bool ParseLineTable(SourceManager &SourceMgr, unsigned FilenameLen = Record[Idx++]; std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen); Idx += FilenameLen; - FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(), + MaybeAddSystemRootToFilename(Filename); + FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(), Filename.size()); } @@ -693,7 +693,7 @@ static bool ParseLineTable(SourceManager &SourceMgr, unsigned FileOffset = Record[Idx++]; unsigned LineNo = Record[Idx++]; int FilenameID = Record[Idx++]; - SrcMgr::CharacteristicKind FileKind + SrcMgr::CharacteristicKind FileKind = (SrcMgr::CharacteristicKind)Record[Idx++]; unsigned IncludeOffset = Record[Idx++]; Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID, @@ -715,10 +715,10 @@ public: const mode_t mode; const time_t mtime; const off_t size; - + PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s) - : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {} - + : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {} + PCHStatData() : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {} }; @@ -761,7 +761,7 @@ class VISIBILITY_HIDDEN PCHStatLookupTrait { ino_t ino = (ino_t) ReadUnalignedLE32(d); dev_t dev = (dev_t) ReadUnalignedLE32(d); mode_t mode = (mode_t) ReadUnalignedLE16(d); - time_t mtime = (time_t) ReadUnalignedLE64(d); + time_t mtime = (time_t) ReadUnalignedLE64(d); off_t size = (off_t) ReadUnalignedLE64(d); return data_type(ino, dev, mode, mtime, size); } @@ -776,17 +776,17 @@ class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache { CacheTy *Cache; unsigned &NumStatHits, &NumStatMisses; -public: +public: PCHStatCache(const unsigned char *Buckets, const unsigned char *Base, unsigned &NumStatHits, - unsigned &NumStatMisses) + unsigned &NumStatMisses) : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) { Cache = CacheTy::Create(Buckets, Base); } ~PCHStatCache() { delete Cache; } - + int stat(const char *path, struct stat *buf) { // Do the lookup for the file's data in the PCH file. CacheTy::iterator I = Cache->find(path); @@ -796,10 +796,10 @@ public: ++NumStatMisses; return ::stat(path, buf); } - + ++NumStatHits; PCHStatData Data = *I; - + if (!Data.hasStat) return 1; @@ -846,7 +846,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { } return Success; } - + if (Code == llvm::bitc::ENTER_SUBBLOCK) { // No known subblocks, always skip them. SLocEntryCursor.ReadSubBlockID(); @@ -856,12 +856,12 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { } continue; } - + if (Code == llvm::bitc::DEFINE_ABBREV) { SLocEntryCursor.ReadAbbrevRecord(); continue; } - + // Read a record. const char *BlobStart; unsigned BlobLen; @@ -871,7 +871,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { break; case pch::SM_LINE_TABLE: - if (ParseLineTable(SourceMgr, Record)) + if (ParseLineTable(Record)) return Failure; break; @@ -924,15 +924,17 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { return Failure; case pch::SM_SLOC_FILE_ENTRY: { - const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen); + std::string Filename(BlobStart, BlobStart + BlobLen); + MaybeAddSystemRootToFilename(Filename); + const FileEntry *File = FileMgr.getFile(Filename); if (File == 0) { std::string ErrorStr = "could not find file '"; - ErrorStr.append(BlobStart, BlobLen); + ErrorStr += Filename; ErrorStr += "' referenced by PCH file"; Error(ErrorStr.c_str()); return Failure; } - + FileID FID = SourceMgr.createFileID(File, SourceLocation::getFromRawEncoding(Record[1]), (SrcMgr::CharacteristicKind)Record[2], @@ -949,16 +951,16 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { unsigned Offset = Record[0]; unsigned Code = SLocEntryCursor.ReadCode(); Record.clear(); - unsigned RecCode + unsigned RecCode = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file"); (void)RecCode; llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(BlobStart, + = llvm::MemoryBuffer::getMemBuffer(BlobStart, BlobStart + BlobLen - 1, Name); FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); - + if (strcmp(Name, "<built-in>") == 0) { PCHPredefinesBufferID = BufferID; PCHPredefines = BlobStart; @@ -969,7 +971,7 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { } case pch::SM_SLOC_INSTANTIATION_ENTRY: { - SourceLocation SpellingLoc + SourceLocation SpellingLoc = SourceLocation::getFromRawEncoding(Record[1]); SourceMgr.createInstantiationLoc(SpellingLoc, SourceLocation::getFromRawEncoding(Record[2]), @@ -978,7 +980,7 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { ID, Record[0]); break; - } + } } return Success; @@ -993,10 +995,10 @@ bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, Error("malformed block record in PCH file"); return Failure; } - + while (true) { unsigned Code = Cursor.ReadCode(); - + // We expect all abbrevs to be at the start of the block. if (Code != llvm::bitc::DEFINE_ABBREV) return false; @@ -1006,7 +1008,7 @@ bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, void PCHReader::ReadMacroRecord(uint64_t Offset) { assert(PP && "Forgot to set Preprocessor ?"); - + // Keep track of where we are in the stream, then jump back there // after reading this macro. SavedStreamPosition SavedPosition(Stream); @@ -1015,7 +1017,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { RecordData Record; llvm::SmallVector<IdentifierInfo*, 16> MacroArgs; MacroInfo *Macro = 0; - + while (true) { unsigned Code = Stream.ReadCode(); switch (Code) { @@ -1030,7 +1032,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { return; } continue; - + case llvm::bitc::DEFINE_ABBREV: Stream.ReadAbbrevRecord(); continue; @@ -1057,10 +1059,10 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { } SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]); bool isUsed = Record[2]; - + MacroInfo *MI = PP->AllocateMacroInfo(Loc); MI->setIsUsed(isUsed); - + if (RecType == pch::PP_MACRO_FUNCTION_LIKE) { // Decode function-like macro info. bool isC99VarArgs = Record[3]; @@ -1087,12 +1089,12 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { ++NumMacrosRead; break; } - + case pch::PP_TOKEN: { // If we see a TOKEN before a PP_MACRO_*, then the file is // erroneous, just pretend we didn't see this. if (Macro == 0) break; - + Token Tok; Tok.startToken(); Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0])); @@ -1108,7 +1110,33 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { } } -PCHReader::PCHReadResult +/// \brief If we are loading a relocatable PCH file, and the filename is +/// not an absolute path, add the system root to the beginning of the file +/// name. +void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) { + // If this is not a relocatable PCH file, there's nothing to do. + if (!RelocatablePCH) + return; + + if (Filename.empty() || Filename[0] == '/' || Filename[0] == '<') + return; + + std::string FIXME = Filename; + + if (isysroot == 0) { + // If no system root was given, default to '/' + Filename.insert(Filename.begin(), '/'); + return; + } + + unsigned Length = strlen(isysroot); + if (isysroot[Length - 1] != '/') + Filename.insert(Filename.begin(), '/'); + + Filename.insert(Filename.begin(), isysroot, isysroot + Length); +} + +PCHReader::PCHReadResult PCHReader::ReadPCHBlock() { if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { Error("malformed block record in PCH file"); @@ -1151,7 +1179,7 @@ PCHReader::ReadPCHBlock() { return Failure; } break; - + case pch::PREPROCESSOR_BLOCK_ID: if (Stream.SkipBlock()) { Error("malformed block record in PCH file"); @@ -1185,7 +1213,7 @@ PCHReader::ReadPCHBlock() { Record.clear(); const char *BlobStart = 0; unsigned BlobLen = 0; - switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record, + switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { default: // Default behavior: ignore. break; @@ -1220,6 +1248,7 @@ PCHReader::ReadPCHBlock() { return IgnorePCH; } + RelocatablePCH = Record[4]; if (Listener) { std::string TargetTriple(BlobStart, BlobLen); if (Listener->ReadTargetTriple(TargetTriple)) @@ -1231,10 +1260,10 @@ PCHReader::ReadPCHBlock() { case pch::IDENTIFIER_TABLE: IdentifierTableData = BlobStart; if (Record[0]) { - IdentifierLookupTable + IdentifierLookupTable = PCHIdentifierLookupTable::Create( (const unsigned char *)IdentifierTableData + Record[0], - (const unsigned char *)IdentifierTableData, + (const unsigned char *)IdentifierTableData, PCHIdentifierLookupTrait(*this)); if (PP) PP->getIdentifierTable().setExternalIdentifierLookup(this); @@ -1296,10 +1325,10 @@ PCHReader::ReadPCHBlock() { case pch::METHOD_POOL: MethodPoolLookupTableData = (const unsigned char *)BlobStart; if (Record[0]) - MethodPoolLookupTable + MethodPoolLookupTable = PCHMethodPoolLookupTable::Create( MethodPoolLookupTableData + Record[0], - MethodPoolLookupTableData, + MethodPoolLookupTableData, PCHMethodPoolLookupTrait(*this)); TotalSelectorsInMethodPool = Record[1]; break; @@ -1312,9 +1341,7 @@ PCHReader::ReadPCHBlock() { case pch::SOURCE_LOCATION_OFFSETS: SLocOffsets = (const uint32_t *)BlobStart; TotalNumSLocEntries = Record[0]; - SourceMgr.PreallocateSLocEntries(this, - TotalNumSLocEntries, - Record[1]); + SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]); break; case pch::SOURCE_LOCATION_PRELOADS: @@ -1340,22 +1367,32 @@ PCHReader::ReadPCHBlock() { ExtVectorDecls.swap(Record); break; - case pch::OBJC_CATEGORY_IMPLEMENTATIONS: - if (!ObjCCategoryImpls.empty()) { - Error("duplicate OBJC_CATEGORY_IMPLEMENTATIONS record in PCH file"); - return Failure; - } - ObjCCategoryImpls.swap(Record); - break; - case pch::ORIGINAL_FILE_NAME: OriginalFileName.assign(BlobStart, BlobLen); + MaybeAddSystemRootToFilename(OriginalFileName); break; - + case pch::COMMENT_RANGES: Comments = (SourceRange *)BlobStart; NumComments = BlobLen / sizeof(SourceRange); break; + + case pch::SVN_BRANCH_REVISION: { + unsigned CurRevision = getClangSubversionRevision(); + if (Record[0] && CurRevision && Record[0] != CurRevision) { + Diag(Record[0] < CurRevision? diag::warn_pch_version_too_old + : diag::warn_pch_version_too_new); + return IgnorePCH; + } + + const char *CurBranch = getClangSubversionPath(); + if (strncmp(CurBranch, BlobStart, BlobLen)) { + std::string PCHBranch(BlobStart, BlobLen); + Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch; + return IgnorePCH; + } + break; + } } } Error("premature end of bitstream in PCH file"); @@ -1367,15 +1404,20 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { this->FileName = FileName; // Open the PCH file. + // + // FIXME: This shouldn't be here, we should just take a raw_ostream. std::string ErrStr; - Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr)); + if (FileName == "-") + Buffer.reset(llvm::MemoryBuffer::getSTDIN()); + else + Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr)); if (!Buffer) { Error(ErrStr.c_str()); return IgnorePCH; } // Initialize the stream - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), + StreamFile.init((const unsigned char *)Buffer->getBufferStart(), (const unsigned char *)Buffer->getBufferEnd()); Stream.init(StreamFile); @@ -1390,7 +1432,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { while (!Stream.AtEndOfStream()) { unsigned Code = Stream.ReadCode(); - + if (Code != llvm::bitc::ENTER_SUBBLOCK) { Error("invalid record at top-level of PCH file"); return Failure; @@ -1436,15 +1478,15 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { } break; } - } - + } + // Check the predefines buffer. - if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen, + if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen, PCHPredefinesBufferID)) return IgnorePCH; - + if (PP) { - // Initialization of builtins and library builtins occurs before the + // Initialization of keywords and pragmas occurs before the // PCH file is read, so there may be some identifiers that were // loaded into the IdentifierTable before we intercepted the // creation of identifiers. Iterate through the list of known @@ -1461,7 +1503,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { IdEnd = PP->getIdentifierTable().end(); Id != IdEnd; ++Id) Identifiers.push_back(Id->second); - PCHIdentifierLookupTable *IdTable + PCHIdentifierLookupTable *IdTable = (PCHIdentifierLookupTable *)IdentifierLookupTable; for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { IdentifierInfo *II = Identifiers[I]; @@ -1471,7 +1513,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info); if (Pos == IdTable->end()) continue; - + // Dereferencing the iterator has the effect of populating the // IdentifierInfo node with the various declarations it needs. (void)*Pos; @@ -1491,7 +1533,7 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { assert(PP && "Forgot to set Preprocessor ?"); PP->getIdentifierTable().setExternalIdentifierLookup(this); PP->getHeaderSearchInfo().SetExternalLookup(this); - + // Load the translation unit declaration ReadDeclRecord(DeclOffsets[0], 0); @@ -1506,11 +1548,51 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { Context->setObjCProtoType(GetType(Proto)); if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS]) Context->setObjCClassType(GetType(Class)); + if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING]) Context->setCFConstantStringType(GetType(String)); - if (unsigned FastEnum + if (unsigned FastEnum = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE]) Context->setObjCFastEnumerationStateType(GetType(FastEnum)); + if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) { + QualType FileType = GetType(File); + assert(!FileType.isNull() && "FILE type is NULL"); + if (const TypedefType *Typedef = FileType->getAs<TypedefType>()) + Context->setFILEDecl(Typedef->getDecl()); + else { + const TagType *Tag = FileType->getAs<TagType>(); + assert(Tag && "Invalid FILE type in PCH file"); + Context->setFILEDecl(Tag->getDecl()); + } + } + if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) { + QualType Jmp_bufType = GetType(Jmp_buf); + assert(!Jmp_bufType.isNull() && "jmp_bug type is NULL"); + if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>()) + Context->setjmp_bufDecl(Typedef->getDecl()); + else { + const TagType *Tag = Jmp_bufType->getAs<TagType>(); + assert(Tag && "Invalid jmp_bug type in PCH file"); + Context->setjmp_bufDecl(Tag->getDecl()); + } + } + if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) { + QualType Sigjmp_bufType = GetType(Sigjmp_buf); + assert(!Sigjmp_bufType.isNull() && "sigjmp_buf type is NULL"); + if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>()) + Context->setsigjmp_bufDecl(Typedef->getDecl()); + else { + const TagType *Tag = Sigjmp_bufType->getAs<TagType>(); + assert(Tag && "Invalid sigjmp_buf type in PCH file"); + Context->setsigjmp_bufDecl(Tag->getDecl()); + } + } + if (unsigned ObjCIdRedef + = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION]) + Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef); + if (unsigned ObjCClassRedef + = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) + Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); } /// \brief Retrieve the name of the original source file name @@ -1529,7 +1611,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) { // Initialize the stream llvm::BitstreamReader StreamFile; llvm::BitstreamCursor Stream; - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), + StreamFile.init((const unsigned char *)Buffer->getBufferStart(), (const unsigned char *)Buffer->getBufferEnd()); Stream.init(StreamFile); @@ -1538,7 +1620,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) { Stream.Read(8) != 'P' || Stream.Read(8) != 'C' || Stream.Read(8) != 'H') { - fprintf(stderr, + fprintf(stderr, "error: '%s' does not appear to be a precompiled header file\n", PCHFileName.c_str()); return std::string(); @@ -1547,10 +1629,10 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) { RecordData Record; while (!Stream.AtEndOfStream()) { unsigned Code = Stream.ReadCode(); - + if (Code == llvm::bitc::ENTER_SUBBLOCK) { unsigned BlockID = Stream.ReadSubBlockID(); - + // We only know the PCH subblock ID. switch (BlockID) { case pch::PCH_BLOCK_ID: @@ -1559,7 +1641,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) { return std::string(); } break; - + default: if (Stream.SkipBlock()) { fprintf(stderr, "error: malformed block record in PCH file\n"); @@ -1586,10 +1668,10 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) { Record.clear(); const char *BlobStart = 0; unsigned BlobLen = 0; - if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) + if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) == pch::ORIGINAL_FILE_NAME) return std::string(BlobStart, BlobLen); - } + } return std::string(); } @@ -1612,11 +1694,11 @@ bool PCHReader::ParseLanguageOptions( const llvm::SmallVectorImpl<uint64_t> &Record) { if (Listener) { LangOptions LangOpts; - + #define PARSE_LANGOPT(Option) \ LangOpts.Option = Record[Idx]; \ ++Idx - + unsigned Idx = 0; PARSE_LANGOPT(Trigraphs); PARSE_LANGOPT(BCPLComment); @@ -1643,6 +1725,7 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(Freestanding); PARSE_LANGOPT(NoBuiltin); PARSE_LANGOPT(ThreadsafeStatics); + PARSE_LANGOPT(POSIXThreads); PARSE_LANGOPT(Blocks); PARSE_LANGOPT(EmitAllDecls); PARSE_LANGOPT(MathErrno); @@ -1660,6 +1743,9 @@ bool PCHReader::ParseLanguageOptions( ++Idx; LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]); ++Idx; + LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode) + Record[Idx]); + ++Idx; PARSE_LANGOPT(InstantiationDepth); PARSE_LANGOPT(OpenCL); #undef PARSE_LANGOPT @@ -1686,23 +1772,19 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { // after reading this type. SavedStreamPosition SavedPosition(Stream); + // Note that we are loading a type record. + LoadingTypeOrDecl Loading(*this); + Stream.JumpToBit(Offset); RecordData Record; unsigned Code = Stream.ReadCode(); switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) { case pch::TYPE_EXT_QUAL: { - assert(Record.size() == 3 && + assert(Record.size() == 2 && "Incorrect encoding of extended qualifier type"); QualType Base = GetType(Record[0]); - QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1]; - unsigned AddressSpace = Record[2]; - - QualType T = Base; - if (GCAttr != QualType::GCNone) - T = Context->getObjCGCQualType(T, GCAttr); - if (AddressSpace) - T = Context->getAddrSpaceQualType(T, AddressSpace); - return T; + Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]); + return Context->getQualifiedType(Base, Quals); } case pch::TYPE_FIXED_WIDTH_INT: { @@ -1753,7 +1835,32 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { unsigned IndexTypeQuals = Record[2]; unsigned Idx = 3; llvm::APInt Size = ReadAPInt(Record, Idx); - return Context->getConstantArrayType(ElementType, Size, ASM,IndexTypeQuals); + return Context->getConstantArrayType(ElementType, Size, + ASM, IndexTypeQuals); + } + + case pch::TYPE_CONSTANT_ARRAY_WITH_EXPR: { + QualType ElementType = GetType(Record[0]); + ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; + unsigned IndexTypeQuals = Record[2]; + SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); + SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); + unsigned Idx = 5; + llvm::APInt Size = ReadAPInt(Record, Idx); + return Context->getConstantArrayWithExprType(ElementType, + Size, ReadTypeExpr(), + ASM, IndexTypeQuals, + SourceRange(LBLoc, RBLoc)); + } + + case pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR: { + QualType ElementType = GetType(Record[0]); + ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; + unsigned IndexTypeQuals = Record[2]; + unsigned Idx = 3; + llvm::APInt Size = ReadAPInt(Record, Idx); + return Context->getConstantArrayWithoutExprType(ElementType, Size, + ASM, IndexTypeQuals); } case pch::TYPE_INCOMPLETE_ARRAY: { @@ -1767,8 +1874,11 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { QualType ElementType = GetType(Record[0]); ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; unsigned IndexTypeQuals = Record[2]; + SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); + SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); return Context->getVariableArrayType(ElementType, ReadTypeExpr(), - ASM, IndexTypeQuals); + ASM, IndexTypeQuals, + SourceRange(LBLoc, RBLoc)); } case pch::TYPE_VECTOR: { @@ -1838,7 +1948,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { QualType UnderlyingType = GetType(Record[0]); return Context->getTypeOfType(UnderlyingType); } - + case pch::TYPE_DECLTYPE: return Context->getDecltypeType(ReadTypeExpr()); @@ -1850,30 +1960,41 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { assert(Record.size() == 1 && "incorrect encoding of enum type"); return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0]))); - case pch::TYPE_OBJC_INTERFACE: - assert(Record.size() == 1 && "incorrect encoding of objc interface type"); - return Context->getObjCInterfaceType( - cast<ObjCInterfaceDecl>(GetDecl(Record[0]))); + case pch::TYPE_ELABORATED: { + assert(Record.size() == 2 && "incorrect encoding of elaborated type"); + unsigned Tag = Record[1]; + return Context->getElaboratedType(GetType(Record[0]), + (ElaboratedType::TagKind) Tag); + } - case pch::TYPE_OBJC_QUALIFIED_INTERFACE: { + case pch::TYPE_OBJC_INTERFACE: { unsigned Idx = 0; ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); unsigned NumProtos = Record[Idx++]; llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; for (unsigned I = 0; I != NumProtos; ++I) Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); - return Context->getObjCQualifiedInterfaceType(ItfD, Protos.data(), NumProtos); + return Context->getObjCInterfaceType(ItfD, Protos.data(), NumProtos); } case pch::TYPE_OBJC_OBJECT_POINTER: { unsigned Idx = 0; - ObjCInterfaceDecl *ItfD = - cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); + QualType OIT = GetType(Record[Idx++]); + unsigned NumProtos = Record[Idx++]; + llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; + for (unsigned I = 0; I != NumProtos; ++I) + Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); + return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos); + } + + case pch::TYPE_OBJC_PROTOCOL_LIST: { + unsigned Idx = 0; + QualType OIT = GetType(Record[Idx++]); unsigned NumProtos = Record[Idx++]; llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; for (unsigned I = 0; I != NumProtos; ++I) Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); - return Context->getObjCObjectPointerType(ItfD, Protos.data(), NumProtos); + return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos); } } // Suppress a GCC warning @@ -1882,8 +2003,8 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { QualType PCHReader::GetType(pch::TypeID ID) { - unsigned Quals = ID & 0x07; - unsigned Index = ID >> 3; + unsigned FastQuals = ID & Qualifiers::FastMask; + unsigned Index = ID >> Qualifiers::FastWidth; if (Index < pch::NUM_PREDEF_TYPE_IDS) { QualType T; @@ -1917,18 +2038,22 @@ QualType PCHReader::GetType(pch::TypeID ID) { case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break; case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break; case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break; + case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break; + case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break; + case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break; + case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break; } assert(!T.isNull() && "Unknown predefined type"); - return T.getQualifiedType(Quals); + return T.withFastQualifiers(FastQuals); } Index -= pch::NUM_PREDEF_TYPE_IDS; - assert(Index < TypesLoaded.size() && "Type index out-of-range"); - if (!TypesLoaded[Index]) - TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr(); - - return QualType(TypesLoaded[Index], Quals); + //assert(Index < TypesLoaded.size() && "Type index out-of-range"); + if (TypesLoaded[Index].isNull()) + TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]); + + return TypesLoaded[Index].withFastQualifiers(FastQuals); } Decl *PCHReader::GetDecl(pch::DeclID ID) { @@ -1961,7 +2086,7 @@ Stmt *PCHReader::GetDeclStmt(uint64_t Offset) { bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, llvm::SmallVectorImpl<pch::DeclID> &Decls) { - assert(DC->hasExternalLexicalStorage() && + assert(DC->hasExternalLexicalStorage() && "DeclContext has no lexical decls in storage"); uint64_t Offset = DeclContextOffsets[DC].first; assert(Offset && "DeclContext has no lexical decls in storage"); @@ -1988,7 +2113,7 @@ bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, llvm::SmallVectorImpl<VisibleDeclaration> &Decls) { - assert(DC->hasExternalVisibleStorage() && + assert(DC->hasExternalVisibleStorage() && "DeclContext has no visible decls in storage"); uint64_t Offset = DeclContextOffsets[DC].second; assert(Offset && "DeclContext has no visible decls in storage"); @@ -2006,7 +2131,7 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, (void)RecCode; assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block"); if (Record.size() == 0) - return false; + return false; Decls.clear(); @@ -2033,9 +2158,9 @@ void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { return; for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) { - Decl *D = GetDecl(ExternalDefinitions[I]); - DeclGroupRef DG(D); - Consumer->HandleTopLevelDecl(DG); + // Force deserialization of this decl, which will cause it to be passed to + // the consumer (or queued). + GetDecl(ExternalDefinitions[I]); } for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) { @@ -2047,9 +2172,9 @@ void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { void PCHReader::PrintStats() { std::fprintf(stderr, "*** PCH Statistics:\n"); - unsigned NumTypesLoaded + unsigned NumTypesLoaded = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(), - (Type *)0); + QualType()); unsigned NumDeclsLoaded = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(), (Decl *)0); @@ -2057,7 +2182,7 @@ void PCHReader::PrintStats() { = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(), IdentifiersLoaded.end(), (IdentifierInfo *)0); - unsigned NumSelectorsLoaded + unsigned NumSelectorsLoaded = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(), SelectorsLoaded.end(), Selector()); @@ -2129,6 +2254,7 @@ void PCHReader::InitializeSema(Sema &S) { 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()); } // If there were any locally-scoped external declarations, @@ -2144,18 +2270,11 @@ void PCHReader::InitializeSema(Sema &S) { for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) SemaObj->ExtVectorDecls.push_back( cast<TypedefDecl>(GetDecl(ExtVectorDecls[I]))); - - // If there were any Objective-C category implementations, - // deserialize them and add them to Sema's vector of such - // definitions. - for (unsigned I = 0, N = ObjCCategoryImpls.size(); I != N; ++I) - SemaObj->ObjCCategoryImpls.push_back( - cast<ObjCCategoryImplDecl>(GetDecl(ObjCCategoryImpls[I]))); } IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) { // Try to find this name within our on-disk hash table - PCHIdentifierLookupTable *IdTable + PCHIdentifierLookupTable *IdTable = (PCHIdentifierLookupTable *)IdentifierLookupTable; std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart); PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key); @@ -2168,7 +2287,7 @@ IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) { return *Pos; } -std::pair<ObjCMethodList, ObjCMethodList> +std::pair<ObjCMethodList, ObjCMethodList> PCHReader::ReadMethodPool(Selector Sel) { if (!MethodPoolLookupTable) return std::pair<ObjCMethodList, ObjCMethodList>(); @@ -2192,15 +2311,61 @@ void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) { IdentifiersLoaded[ID - 1] = II; } +/// \brief Set the globally-visible declarations associated with the given +/// identifier. +/// +/// If the PCH reader is currently in a state where the given declaration IDs +/// cannot safely be resolved, they are queued until it is safe to resolve +/// them. +/// +/// \param II an IdentifierInfo that refers to one or more globally-visible +/// declarations. +/// +/// \param DeclIDs the set of declaration IDs with the name @p II that are +/// visible at global scope. +/// +/// \param Nonrecursive should be true to indicate that the caller knows that +/// this call is non-recursive, and therefore the globally-visible declarations +/// will not be placed onto the pending queue. +void +PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II, + const llvm::SmallVectorImpl<uint32_t> &DeclIDs, + bool Nonrecursive) { + if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) { + PendingIdentifierInfos.push_back(PendingIdentifierInfo()); + PendingIdentifierInfo &PII = PendingIdentifierInfos.back(); + PII.II = II; + for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) + PII.DeclIDs.push_back(DeclIDs[I]); + return; + } + + for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { + NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); + if (SemaObj) { + // Introduce this declaration into the translation-unit scope + // and add it to the declaration chain for this identifier, so + // that (unqualified) name lookup will find it. + SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D)); + SemaObj->IdResolver.AddDeclToIdentifierChain(II, D); + } else { + // Queue this declaration so that it will be added to the + // translation unit scope and identifier's declaration chain + // once a Sema object is known. + PreloadedDecls.push_back(D); + } + } +} + IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) { if (ID == 0) return 0; - + if (!IdentifierTableData || IdentifiersLoaded.empty()) { Error("no identifier table in PCH file"); return 0; } - + assert(PP && "Forgot to set Preprocessor ?"); if (!IdentifiersLoaded[ID - 1]) { uint32_t Offset = IdentifierOffsets[ID - 1]; @@ -2212,10 +2377,10 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) { const char *StrLenPtr = Str - 2; unsigned StrLen = (((unsigned) StrLenPtr[0]) | (((unsigned) StrLenPtr[1]) << 8)) - 1; - IdentifiersLoaded[ID - 1] + IdentifiersLoaded[ID - 1] = &PP->getIdentifierTable().get(Str, Str + StrLen); } - + return IdentifiersLoaded[ID - 1]; } @@ -2226,7 +2391,7 @@ void PCHReader::ReadSLocEntry(unsigned ID) { Selector PCHReader::DecodeSelector(unsigned ID) { if (ID == 0) return Selector(); - + if (!MethodPoolLookupTableData) return Selector(); @@ -2240,14 +2405,14 @@ Selector PCHReader::DecodeSelector(unsigned ID) { // Load this selector from the selector table. // FIXME: endianness portability issues with SelectorOffsets table PCHMethodPoolLookupTrait Trait(*this); - SelectorsLoaded[Index] + SelectorsLoaded[Index] = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0); } return SelectorsLoaded[Index]; } -DeclarationName +DeclarationName PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; switch (Kind) { @@ -2261,15 +2426,15 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { case DeclarationName::CXXConstructorName: return Context->DeclarationNames.getCXXConstructorName( - GetType(Record[Idx++])); + Context->getCanonicalType(GetType(Record[Idx++]))); case DeclarationName::CXXDestructorName: return Context->DeclarationNames.getCXXDestructorName( - GetType(Record[Idx++])); + Context->getCanonicalType(GetType(Record[Idx++]))); case DeclarationName::CXXConversionFunctionName: return Context->DeclarationNames.getCXXConversionFunctionName( - GetType(Record[Idx++])); + Context->getCanonicalType(GetType(Record[Idx++]))); case DeclarationName::CXXOperatorName: return Context->DeclarationNames.getCXXOperatorName( @@ -2342,7 +2507,7 @@ SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) { /// \brief Record that the given label statement has been /// deserialized and has the given ID. void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) { - assert(LabelStmts.find(ID) == LabelStmts.end() && + assert(LabelStmts.find(ID) == LabelStmts.end() && "Deserialized label twice"); LabelStmts[ID] = S; @@ -2357,9 +2522,9 @@ void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) { // If we've already seen any address-label statements that point to // this label, resolve them now. typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter; - std::pair<AddrLabelIter, AddrLabelIter> AddrLabels + std::pair<AddrLabelIter, AddrLabelIter> AddrLabels = UnresolvedAddrLabelExprs.equal_range(ID); - for (AddrLabelIter AddrLabel = AddrLabels.first; + for (AddrLabelIter AddrLabel = AddrLabels.first; AddrLabel != AddrLabels.second; ++AddrLabel) AddrLabel->second->setLabel(S); UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second); @@ -2404,3 +2569,24 @@ void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) { UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S)); } } + + +PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader) + : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) { + Reader.CurrentlyLoadingTypeOrDecl = this; +} + +PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() { + if (!Parent) { + // If any identifiers with corresponding top-level declarations have + // been loaded, load those declarations now. + while (!Reader.PendingIdentifierInfos.empty()) { + Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II, + Reader.PendingIdentifierInfos.front().DeclIDs, + true); + Reader.PendingIdentifierInfos.pop_front(); + } + } + + Reader.CurrentlyLoadingTypeOrDecl = Parent; +} diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 15b54a2d4fc6..353a6464b18d 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -18,6 +18,7 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/DeclGroup.h" #include "clang/AST/Expr.h" +#include "clang/AST/TypeLocVisitor.h" using namespace clang; @@ -46,6 +47,7 @@ namespace { void VisitRecordDecl(RecordDecl *RD); void VisitValueDecl(ValueDecl *VD); void VisitEnumConstantDecl(EnumConstantDecl *ECD); + void VisitDeclaratorDecl(DeclaratorDecl *DD); void VisitFunctionDecl(FunctionDecl *FD); void VisitFieldDecl(FieldDecl *FD); void VisitVarDecl(VarDecl *VD); @@ -92,7 +94,7 @@ void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) { VisitDecl(ND); - ND->setDeclName(Reader.ReadDeclarationName(Record, Idx)); + ND->setDeclName(Reader.ReadDeclarationName(Record, Idx)); } void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) { @@ -112,10 +114,14 @@ void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) { void PCHDeclReader::VisitTagDecl(TagDecl *TD) { VisitTypeDecl(TD); + TD->setPreviousDeclaration( + cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++]))); TD->setTagKind((TagDecl::TagKind)Record[Idx++]); TD->setDefinition(Record[Idx++]); TD->setTypedefForAnonDecl( cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++]))); + TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -128,6 +134,7 @@ void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) { VisitTagDecl(RD); RD->setHasFlexibleArrayMember(Record[Idx++]); RD->setAnonymousStructOrUnion(Record[Idx++]); + RD->setHasObjectMember(Record[Idx++]); } void PCHDeclReader::VisitValueDecl(ValueDecl *VD) { @@ -142,21 +149,99 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { ECD->setInitVal(Reader.ReadAPSInt(Record, Idx)); } +namespace { + +class TypeLocReader : public TypeLocVisitor<TypeLocReader> { + PCHReader &Reader; + const PCHReader::RecordData &Record; + unsigned &Idx; + +public: + TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record, + unsigned &Idx) + : Reader(Reader), Record(Record), Idx(Idx) { } + +#define ABSTRACT_TYPELOC(CLASS) +#define TYPELOC(CLASS, PARENT, TYPE) \ + void Visit##CLASS(CLASS TyLoc); +#include "clang/AST/TypeLocNodes.def" + + void VisitTypeLoc(TypeLoc TyLoc) { + assert(0 && "A type loc wrapper was not handled!"); + } +}; + +} + +void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { + TyLoc.setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitTypedefLoc(TypedefLoc TyLoc) { + TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) { + TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { + TyLoc.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TyLoc.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i) + TyLoc.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitPointerLoc(PointerLoc TyLoc) { + TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitBlockPointerLoc(BlockPointerLoc TyLoc) { + TyLoc.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitMemberPointerLoc(MemberPointerLoc TyLoc) { + TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitReferenceLoc(ReferenceLoc TyLoc) { + TyLoc.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitFunctionLoc(FunctionLoc TyLoc) { + TyLoc.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TyLoc.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i) + TyLoc.setArg(i, cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); +} +void TypeLocReader::VisitArrayLoc(ArrayLoc TyLoc) { + TyLoc.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TyLoc.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + if (Record[Idx++]) + TyLoc.setSizeExpr(Reader.ReadDeclExpr()); +} + +void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { + VisitValueDecl(DD); + QualType InfoTy = Reader.GetType(Record[Idx++]); + if (InfoTy.isNull()) + return; + + DeclaratorInfo *DInfo = Reader.getContext()->CreateDeclaratorInfo(InfoTy); + TypeLocReader TLR(Reader, Record, Idx); + for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) + TLR.Visit(TL); + DD->setDeclaratorInfo(DInfo); +} + void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { - VisitValueDecl(FD); + VisitDeclaratorDecl(FD); if (Record[Idx++]) FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo()); FD->setPreviousDeclaration( cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); FD->setInline(Record[Idx++]); - FD->setC99InlineDefinition(Record[Idx++]); FD->setVirtualAsWritten(Record[Idx++]); FD->setPure(Record[Idx++]); FD->setHasInheritedPrototype(Record[Idx++]); FD->setHasWrittenPrototype(Record[Idx++]); FD->setDeleted(Record[Idx++]); - FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + FD->setTrivial(Record[Idx++]); + FD->setCopyAssignment(Record[Idx++]); + FD->setHasImplicitReturnZero(Record[Idx++]); FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); // FIXME: C++ TemplateOrInstantiation unsigned NumParams = Record[Idx++]; @@ -219,7 +304,7 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { ID->setImplicitInterfaceDecl(Record[Idx++]); ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - ID->setAtEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); } void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { @@ -301,10 +386,9 @@ void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { } void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitNamedDecl(D); + VisitObjCContainerDecl(D); D->setClassInterface( cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); - D->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); } void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { @@ -329,21 +413,20 @@ void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { } void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) { - VisitValueDecl(FD); + VisitDeclaratorDecl(FD); FD->setMutable(Record[Idx++]); if (Record[Idx++]) FD->setBitWidth(Reader.ReadDeclExpr()); } void PCHDeclReader::VisitVarDecl(VarDecl *VD) { - VisitValueDecl(VD); + VisitDeclaratorDecl(VD); VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]); VD->setThreadSpecified(Record[Idx++]); VD->setCXXDirectInitializer(Record[Idx++]); VD->setDeclaredInCondition(Record[Idx++]); VD->setPreviousDeclaration( cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); - VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); if (Record[Idx++]) VD->setInit(*Reader.getContext(), Reader.ReadDeclExpr()); } @@ -355,7 +438,6 @@ void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { VisitVarDecl(PD); PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); - // FIXME: default argument (C++ only) } void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) { @@ -376,10 +458,10 @@ 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(*Reader.getContext(), Params.data(), NumParams); } -std::pair<uint64_t, uint64_t> +std::pair<uint64_t, uint64_t> PCHDeclReader::VisitDeclContext(DeclContext *DC) { uint64_t LexicalOffset = Record[Idx++]; uint64_t VisibleOffset = Record[Idx++]; @@ -393,13 +475,13 @@ PCHDeclReader::VisitDeclContext(DeclContext *DC) { /// \brief Reads attributes from the current stream position. Attr *PCHReader::ReadAttributes() { unsigned Code = DeclsCursor.ReadCode(); - assert(Code == llvm::bitc::UNABBREV_RECORD && + assert(Code == llvm::bitc::UNABBREV_RECORD && "Expected unabbreviated record"); (void)Code; - + RecordData Record; unsigned Idx = 0; unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - assert(RecCode == pch::DECL_ATTR && "Expected attribute record"); + assert(RecCode == pch::DECL_ATTR && "Expected attribute record"); (void)RecCode; #define SIMPLE_ATTR(Name) \ @@ -430,12 +512,12 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(AnalyzerNoReturn); STRING_ATTR(Annotate); STRING_ATTR(AsmLabel); - + case Attr::Blocks: New = ::new (*Context) BlocksAttr( (BlocksAttr::BlocksAttrTypes)Record[Idx++]); break; - + case Attr::Cleanup: New = ::new (*Context) CleanupAttr( cast<FunctionDecl>(GetDecl(Record[Idx++]))); @@ -448,7 +530,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(Deprecated); UNSIGNED_ATTR(Destructor); SIMPLE_ATTR(FastCall); - + case Attr::Format: { std::string Type = ReadString(Record, Idx); unsigned FormatIdx = Record[Idx++]; @@ -456,13 +538,13 @@ Attr *PCHReader::ReadAttributes() { New = ::new (*Context) FormatAttr(Type, FormatIdx, FirstArg); break; } - + case Attr::FormatArg: { unsigned FormatIdx = Record[Idx++]; New = ::new (*Context) FormatArgAttr(FormatIdx); break; } - + case Attr::Sentinel: { int sentinel = Record[Idx++]; int nullPos = Record[Idx++]; @@ -471,16 +553,17 @@ Attr *PCHReader::ReadAttributes() { } SIMPLE_ATTR(GNUInline); - + case Attr::IBOutletKind: New = ::new (*Context) IBOutletAttr(); break; + SIMPLE_ATTR(Malloc); + SIMPLE_ATTR(NoDebug); + SIMPLE_ATTR(NoInline); SIMPLE_ATTR(NoReturn); SIMPLE_ATTR(NoThrow); - SIMPLE_ATTR(Nodebug); - SIMPLE_ATTR(Noinline); - + case Attr::NonNull: { unsigned Size = Record[Idx++]; llvm::SmallVector<unsigned, 16> ArgNums; @@ -489,7 +572,7 @@ Attr *PCHReader::ReadAttributes() { New = ::new (*Context) NonNullAttr(ArgNums.data(), Size); break; } - + case Attr::ReqdWorkGroupSize: { unsigned X = Record[Idx++]; unsigned Y = Record[Idx++]; @@ -503,7 +586,8 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(CFReturnsRetained); SIMPLE_ATTR(NSReturnsRetained); SIMPLE_ATTR(Overloadable); - UNSIGNED_ATTR(Packed); + SIMPLE_ATTR(Packed); + UNSIGNED_ATTR(PragmaPack); SIMPLE_ATTR(Pure); UNSIGNED_ATTR(Regparm); STRING_ATTR(Section); @@ -512,7 +596,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(Unavailable); SIMPLE_ATTR(Unused); SIMPLE_ATTR(Used); - + case Attr::Visibility: New = ::new (*Context) VisibilityAttr( (VisibilityAttr::VisibilityTypes)Record[Idx++]); @@ -551,7 +635,7 @@ Attr *PCHReader::ReadAttributes() { /// \brief Note that we have loaded the declaration with the given /// Index. -/// +/// /// This routine notes that this declaration has already been loaded, /// so that future GetDecl calls will return this declaration rather /// than trying to load a new declaration. @@ -568,6 +652,8 @@ inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) { /// code generation, e.g., inline function definitions, Objective-C /// declarations with metadata, etc. static bool isConsumerInterestedIn(Decl *D) { + if (isa<FileScopeAsmDecl>(D)) + return true; if (VarDecl *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && Var->getInit(); if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) @@ -581,6 +667,9 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { // after reading this declaration. SavedStreamPosition SavedPosition(DeclsCursor); + // Note that we are loading a declaration record. + LoadingTypeOrDecl Loading(*this); + DeclsCursor.JumpToBit(Offset); RecordData Record; unsigned Code = DeclsCursor.ReadCode(); @@ -602,36 +691,36 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, QualType()); break; case pch::DECL_ENUM: - D = EnumDecl::Create(*Context, 0, SourceLocation(), 0, 0); + D = EnumDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), 0); break; case pch::DECL_RECORD: D = RecordDecl::Create(*Context, TagDecl::TK_struct, 0, SourceLocation(), - 0, 0); + 0, SourceLocation(), 0); break; case pch::DECL_ENUM_CONSTANT: D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, llvm::APSInt()); break; case pch::DECL_FUNCTION: - D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(), - QualType()); + D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(), + QualType(), 0); break; case pch::DECL_OBJC_METHOD: - D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(), + D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(), Selector(), QualType(), 0); break; case pch::DECL_OBJC_INTERFACE: D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); break; case pch::DECL_OBJC_IVAR: - D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), + D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, ObjCIvarDecl::None); break; case pch::DECL_OBJC_PROTOCOL: D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0); break; case pch::DECL_OBJC_AT_DEFS_FIELD: - D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0, + D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0); break; case pch::DECL_OBJC_CLASS: @@ -657,16 +746,16 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { break; case pch::DECL_OBJC_PROPERTY_IMPL: D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), 0, + SourceLocation(), 0, ObjCPropertyImplDecl::Dynamic, 0); break; case pch::DECL_FIELD: - D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, + D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0, false); break; case pch::DECL_VAR: - D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), - VarDecl::None, SourceLocation()); + D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, + VarDecl::None); break; case pch::DECL_IMPLICIT_PARAM: @@ -674,12 +763,12 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { break; case pch::DECL_PARM_VAR: - D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), + D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, VarDecl::None, 0); break; case pch::DECL_ORIGINAL_PARM_VAR: D = OriginalParmVarDecl::Create(*Context, 0, SourceLocation(), 0, - QualType(), QualType(), VarDecl::None, 0); + QualType(),0, QualType(), VarDecl::None, 0); break; case pch::DECL_FILE_SCOPE_ASM: D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0); @@ -719,4 +808,3 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { return D; } - diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index eccb53bf8189..4b9496e00f8b 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/PCHReader.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/StmtVisitor.h" using namespace clang; @@ -101,16 +102,21 @@ namespace { unsigned VisitObjCProtocolExpr(ObjCProtocolExpr *E); unsigned VisitObjCIvarRefExpr(ObjCIvarRefExpr *E); unsigned VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E); - unsigned VisitObjCKVCRefExpr(ObjCKVCRefExpr *E); + unsigned VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *E); unsigned VisitObjCMessageExpr(ObjCMessageExpr *E); unsigned VisitObjCSuperExpr(ObjCSuperExpr *E); - + unsigned VisitObjCIsaExpr(ObjCIsaExpr *E); + unsigned VisitObjCForCollectionStmt(ObjCForCollectionStmt *); unsigned VisitObjCAtCatchStmt(ObjCAtCatchStmt *); unsigned VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); unsigned VisitObjCAtTryStmt(ObjCAtTryStmt *); unsigned VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); unsigned VisitObjCAtThrowStmt(ObjCAtThrowStmt *); + + unsigned VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); + unsigned VisitCXXConstructExpr(CXXConstructExpr *E); }; } @@ -128,7 +134,7 @@ unsigned PCHStmtReader::VisitNullStmt(NullStmt *S) { unsigned PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) { VisitStmt(S); unsigned NumStmts = Record[Idx++]; - S->setStmts(*Reader.getContext(), + S->setStmts(*Reader.getContext(), StmtStack.data() + StmtStack.size() - NumStmts, NumStmts); S->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -191,6 +197,10 @@ unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) { PrevSC->setNextSwitchCase(SC); else S->setSwitchCaseList(SC); + + // Retain this SwitchCase, since SwitchStmt::addSwitchCase() would + // normally retain it (but we aren't calling addSwitchCase). + SC->Retain(); PrevSC = SC; } return 2; @@ -290,8 +300,8 @@ unsigned PCHStmtReader::VisitAsmStmt(AsmStmt *S) { S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); S->setVolatile(Record[Idx++]); S->setSimple(Record[Idx++]); - - unsigned StackIdx + + unsigned StackIdx = StmtStack.size() - (NumOutputs*2 + NumInputs*2 + NumClobbers + 1); S->setAsmString(cast_or_null<StringLiteral>(StmtStack[StackIdx++])); @@ -364,14 +374,14 @@ unsigned PCHStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) { unsigned PCHStmtReader::VisitStringLiteral(StringLiteral *E) { VisitExpr(E); unsigned Len = Record[Idx++]; - assert(Record[Idx] == E->getNumConcatenated() && + assert(Record[Idx] == E->getNumConcatenated() && "Wrong number of concatenated tokens!"); ++Idx; E->setWide(Record[Idx++]); - // Read string data - llvm::SmallVector<char, 16> Str(&Record[Idx], &Record[Idx] + Len); - E->setStrData(*Reader.getContext(), Str.data(), Len); + // Read string data + llvm::SmallString<16> Str(&Record[Idx], &Record[Idx] + Len); + E->setString(*Reader.getContext(), Str.str()); Idx += Len; // Read source locations @@ -446,9 +456,19 @@ unsigned PCHStmtReader::VisitMemberExpr(MemberExpr *E) { return 1; } +unsigned PCHStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) { + VisitExpr(E); + E->setBase(cast<Expr>(StmtStack.back())); + E->setIsaMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + E->setArrow(Record[Idx++]); + return 1; +} + unsigned PCHStmtReader::VisitCastExpr(CastExpr *E) { VisitExpr(E); E->setSubExpr(cast<Expr>(StmtStack.back())); + E->setCastKind((CastExpr::CastKind)Record[Idx++]); + return 1; } @@ -473,6 +493,8 @@ unsigned PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) { E->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3])); E->setLHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2])); E->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 1])); + E->setQuestionLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + E->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); return 3; } @@ -516,7 +538,7 @@ unsigned PCHStmtReader::VisitInitListExpr(InitListExpr *E) { unsigned NumInits = Record[Idx++]; E->reserveInits(NumInits); for (unsigned I = 0; I != NumInits; ++I) - E->updateInit(I, + E->updateInit(I, cast<Expr>(StmtStack[StmtStack.size() - NumInits - 1 + I])); E->setSyntacticForm(cast_or_null<InitListExpr>(StmtStack.back())); E->setLBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -543,11 +565,11 @@ unsigned PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { switch ((pch::DesignatorTypes)Record[Idx++]) { case pch::DESIG_FIELD_DECL: { FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++])); - SourceLocation DotLoc + SourceLocation DotLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation FieldLoc + SourceLocation FieldLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); - Designators.push_back(Designator(Field->getIdentifier(), DotLoc, + Designators.push_back(Designator(Field->getIdentifier(), DotLoc, FieldLoc)); Designators.back().setField(Field); break; @@ -555,14 +577,14 @@ unsigned PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { case pch::DESIG_FIELD_NAME: { const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx); - SourceLocation DotLoc + SourceLocation DotLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation FieldLoc + SourceLocation FieldLoc = SourceLocation::getFromRawEncoding(Record[Idx++]); Designators.push_back(Designator(Name, DotLoc, FieldLoc)); break; } - + case pch::DESIG_ARRAY: { unsigned Index = Record[Idx++]; SourceLocation LBracketLoc @@ -649,7 +671,8 @@ unsigned PCHStmtReader::VisitGNUNullExpr(GNUNullExpr *E) { unsigned PCHStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { VisitExpr(E); unsigned NumExprs = Record[Idx++]; - E->setExprs((Expr **)&StmtStack[StmtStack.size() - NumExprs], NumExprs); + E->setExprs(*Reader.getContext(), + (Expr **)&StmtStack[StmtStack.size() - NumExprs], NumExprs); E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); return NumExprs; @@ -723,13 +746,14 @@ unsigned PCHStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { return 1; } -unsigned PCHStmtReader::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { +unsigned PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *E) { VisitExpr(E); E->setGetterMethod( cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); E->setSetterMethod( cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - E->setClassProp( + E->setInterfaceDecl( cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); E->setBase(cast_or_null<Expr>(StmtStack.back())); E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -744,7 +768,7 @@ unsigned PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) { E->setRightLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); E->setSelector(Reader.GetSelector(Record, Idx)); E->setMethodDecl(cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); - + E->setReceiver( cast_or_null<Expr>(StmtStack[StmtStack.size() - E->getNumArgs() - 1])); if (!E->getReceiver()) { @@ -816,6 +840,23 @@ unsigned PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { return 1; } +//===----------------------------------------------------------------------===// +// C++ Expressions and Statements + +unsigned PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + unsigned num = VisitCallExpr(E); + E->setOperator((OverloadedOperatorKind)Record[Idx++]); + return num; +} + +unsigned PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { + VisitExpr(E); + E->setConstructor(cast<CXXConstructorDecl>(Reader.GetDecl(Record[Idx++]))); + E->setElidable(Record[Idx++]); + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) + E->setArg(I, cast<Expr>(StmtStack[StmtStack.size() - N + I])); + return E->getNumArgs(); +} // Within the bitstream, expressions are stored in Reverse Polish // Notation, with each of the subexpressions preceding the @@ -865,8 +906,8 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { Finished = true; break; - case pch::STMT_NULL_PTR: - S = 0; + case pch::STMT_NULL_PTR: + S = 0; break; case pch::STMT_NULL: @@ -904,7 +945,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::STMT_DO: S = new (Context) DoStmt(Empty); break; - + case pch::STMT_FOR: S = new (Context) ForStmt(Empty); break; @@ -912,7 +953,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::STMT_GOTO: S = new (Context) GotoStmt(Empty); break; - + case pch::STMT_INDIRECT_GOTO: S = new (Context) IndirectGotoStmt(Empty); break; @@ -940,25 +981,25 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::EXPR_PREDEFINED: S = new (Context) PredefinedExpr(Empty); break; - - case pch::EXPR_DECL_REF: - S = new (Context) DeclRefExpr(Empty); + + case pch::EXPR_DECL_REF: + S = new (Context) DeclRefExpr(Empty); break; - - case pch::EXPR_INTEGER_LITERAL: + + case pch::EXPR_INTEGER_LITERAL: S = new (Context) IntegerLiteral(Empty); break; - + case pch::EXPR_FLOATING_LITERAL: S = new (Context) FloatingLiteral(Empty); break; - + case pch::EXPR_IMAGINARY_LITERAL: S = new (Context) ImaginaryLiteral(Empty); break; case pch::EXPR_STRING_LITERAL: - S = StringLiteral::CreateEmpty(*Context, + S = StringLiteral::CreateEmpty(*Context, Record[PCHStmtReader::NumExprFields + 1]); break; @@ -983,7 +1024,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { break; case pch::EXPR_CALL: - S = new (Context) CallExpr(*Context, Empty); + S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty); break; case pch::EXPR_MEMBER: @@ -1025,7 +1066,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::EXPR_DESIGNATED_INIT: S = DesignatedInitExpr::CreateEmpty(*Context, Record[PCHStmtReader::NumExprFields] - 1); - + break; case pch::EXPR_IMPLICIT_VALUE_INIT: @@ -1059,7 +1100,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::EXPR_SHUFFLE_VECTOR: S = new (Context) ShuffleVectorExpr(Empty); break; - + case pch::EXPR_BLOCK: S = new (Context) BlockExpr(Empty); break; @@ -1067,7 +1108,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::EXPR_BLOCK_DECL_REF: S = new (Context) BlockDeclRefExpr(Empty); break; - + case pch::EXPR_OBJC_STRING_LITERAL: S = new (Context) ObjCStringLiteral(Empty); break; @@ -1087,7 +1128,7 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { S = new (Context) ObjCPropertyRefExpr(Empty); break; case pch::EXPR_OBJC_KVC_REF_EXPR: - S = new (Context) ObjCKVCRefExpr(Empty); + S = new (Context) ObjCImplicitSetterGetterRefExpr(Empty); break; case pch::EXPR_OBJC_MESSAGE_EXPR: S = new (Context) ObjCMessageExpr(Empty); @@ -1095,6 +1136,9 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::EXPR_OBJC_SUPER_EXPR: S = new (Context) ObjCSuperExpr(Empty); break; + case pch::EXPR_OBJC_ISA: + S = new (Context) ObjCIsaExpr(Empty); + break; case pch::STMT_OBJC_FOR_COLLECTION: S = new (Context) ObjCForCollectionStmt(Empty); break; @@ -1113,6 +1157,15 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { case pch::STMT_OBJC_AT_THROW: S = new (Context) ObjCAtThrowStmt(Empty); break; + + case pch::EXPR_CXX_OPERATOR_CALL: + S = new (Context) CXXOperatorCallExpr(*Context, Empty); + break; + + case pch::EXPR_CXX_CONSTRUCT: + S = new (Context) CXXConstructExpr(Empty, *Context, + Record[PCHStmtReader::NumExprFields + 2]); + 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 3bfc9e89d10a..64a678ea450b 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -13,7 +13,7 @@ #include "clang/Frontend/PCHWriter.h" #include "../Sema/Sema.h" // FIXME: move header into include/clang/Sema -#include "../Sema/IdentifierResolver.h" // FIXME: move header +#include "../Sema/IdentifierResolver.h" // FIXME: move header #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclContextInternals.h" @@ -50,7 +50,7 @@ namespace { /// \brief Type code that corresponds to the record generated. pch::TypeCode Code; - PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) + PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) : Writer(Writer), Record(Record), Code(pch::TYPE_EXT_QUAL) { } void VisitArrayType(const ArrayType *T); @@ -64,13 +64,6 @@ namespace { }; } -void PCHTypeWriter::VisitExtQualType(const ExtQualType *T) { - Writer.AddTypeRef(QualType(T->getBaseType(), 0), Record); - Record.push_back(T->getObjCGCAttr()); // FIXME: use stable values - Record.push_back(T->getAddressSpace()); - Code = pch::TYPE_EXT_QUAL; -} - void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) { assert(false && "Built-in types are never serialized"); } @@ -92,7 +85,7 @@ void PCHTypeWriter::VisitPointerType(const PointerType *T) { } void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); + Writer.AddTypeRef(T->getPointeeType(), Record); Code = pch::TYPE_BLOCK_POINTER; } @@ -107,15 +100,15 @@ void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) { } void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) { - Writer.AddTypeRef(T->getPointeeType(), Record); - Writer.AddTypeRef(QualType(T->getClass(), 0), Record); + Writer.AddTypeRef(T->getPointeeType(), Record); + Writer.AddTypeRef(QualType(T->getClass(), 0), Record); Code = pch::TYPE_MEMBER_POINTER; } void PCHTypeWriter::VisitArrayType(const ArrayType *T) { Writer.AddTypeRef(T->getElementType(), Record); Record.push_back(T->getSizeModifier()); // FIXME: stable values - Record.push_back(T->getIndexTypeQualifier()); // FIXME: stable values + Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values } void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { @@ -124,6 +117,23 @@ void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) { Code = pch::TYPE_CONSTANT_ARRAY; } +void PCHTypeWriter +::VisitConstantArrayWithExprType(const ConstantArrayWithExprType *T) { + VisitArrayType(T); + Writer.AddSourceLocation(T->getLBracketLoc(), Record); + Writer.AddSourceLocation(T->getRBracketLoc(), Record); + Writer.AddAPInt(T->getSize(), Record); + Writer.AddStmt(T->getSizeExpr()); + Code = pch::TYPE_CONSTANT_ARRAY_WITH_EXPR; +} + +void PCHTypeWriter +::VisitConstantArrayWithoutExprType(const ConstantArrayWithoutExprType *T) { + VisitArrayType(T); + Writer.AddAPInt(T->getSize(), Record); + Code = pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR; +} + void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { VisitArrayType(T); Code = pch::TYPE_INCOMPLETE_ARRAY; @@ -131,6 +141,8 @@ void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) { void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) { VisitArrayType(T); + Writer.AddSourceLocation(T->getLBracketLoc(), Record); + Writer.AddSourceLocation(T->getRBracketLoc(), Record); Writer.AddStmt(T->getSizeExpr()); Code = pch::TYPE_VARIABLE_ARRAY; } @@ -192,7 +204,7 @@ void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) { void PCHTypeWriter::VisitTagType(const TagType *T) { Writer.AddDeclRef(T->getDecl(), Record); - assert(!T->isBeingDefined() && + assert(!T->isBeingDefined() && "Cannot serialize in the middle of a type definition"); } @@ -206,7 +218,13 @@ void PCHTypeWriter::VisitEnumType(const EnumType *T) { Code = pch::TYPE_ENUM; } -void +void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) { + Writer.AddTypeRef(T->getUnderlyingType(), Record); + Record.push_back(T->getTagKind()); + Code = pch::TYPE_ELABORATED; +} + +void PCHTypeWriter::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { // FIXME: Serialize this type (C++ only) @@ -220,23 +238,16 @@ void PCHTypeWriter::VisitQualifiedNameType(const QualifiedNameType *T) { void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { Writer.AddDeclRef(T->getDecl(), Record); - Code = pch::TYPE_OBJC_INTERFACE; -} - -void -PCHTypeWriter::VisitObjCQualifiedInterfaceType( - const ObjCQualifiedInterfaceType *T) { - VisitObjCInterfaceType(T); Record.push_back(T->getNumProtocols()); for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), E = T->qual_end(); I != E; ++I) Writer.AddDeclRef(*I, Record); - Code = pch::TYPE_OBJC_QUALIFIED_INTERFACE; + Code = pch::TYPE_OBJC_INTERFACE; } void PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { - Writer.AddDeclRef(T->getDecl(), Record); + Writer.AddTypeRef(T->getPointeeType(), Record); Record.push_back(T->getNumProtocols()); for (ObjCInterfaceType::qual_iterator I = T->qual_begin(), E = T->qual_end(); I != E; ++I) @@ -244,6 +255,15 @@ PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { Code = pch::TYPE_OBJC_OBJECT_POINTER; } +void PCHTypeWriter::VisitObjCProtocolListType(const ObjCProtocolListType *T) { + Writer.AddTypeRef(T->getBaseType(), Record); + Record.push_back(T->getNumProtocols()); + for (ObjCProtocolListType::qual_iterator I = T->qual_begin(), + E = T->qual_end(); I != E; ++I) + Writer.AddDeclRef(*I, Record); + Code = pch::TYPE_OBJC_PROTOCOL_LIST; +} + //===----------------------------------------------------------------------===// // PCHWriter Implementation //===----------------------------------------------------------------------===// @@ -344,14 +364,14 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(STMT_OBJC_AT_THROW); #undef RECORD } - + void PCHWriter::WriteBlockInfoBlock() { RecordData Record; Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); - + #define BLOCK(X) EmitBlockID(pch::X ## _ID, #X, Stream, Record) #define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record) - + // PCH Top-Level Block. BLOCK(PCH_BLOCK); RECORD(ORIGINAL_FILE_NAME); @@ -373,8 +393,8 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(SOURCE_LOCATION_PRELOADS); RECORD(STAT_CACHE); RECORD(EXT_VECTOR_DECLS); - RECORD(OBJC_CATEGORY_IMPLEMENTATIONS); RECORD(COMMENT_RANGES); + RECORD(SVN_BRANCH_REVISION); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -384,7 +404,7 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(SM_SLOC_INSTANTIATION_ENTRY); RECORD(SM_LINE_TABLE); RECORD(SM_HEADER_FILE_INFO); - + // Preprocessor Block. BLOCK(PREPROCESSOR_BLOCK); RECORD(PP_MACRO_OBJECT_LIKE); @@ -414,8 +434,8 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(TYPE_RECORD); RECORD(TYPE_ENUM); RECORD(TYPE_OBJC_INTERFACE); - RECORD(TYPE_OBJC_QUALIFIED_INTERFACE); RECORD(TYPE_OBJC_OBJECT_POINTER); + RECORD(TYPE_OBJC_PROTOCOL_LIST); // Statements and Exprs can occur in the Types block. AddStmtsExprs(Stream, Record); @@ -457,35 +477,45 @@ void PCHWriter::WriteBlockInfoBlock() { Stream.ExitBlock(); } +/// \brief Adjusts the given filename to only write out the portion of the +/// filename that is not part of the system root directory. +/// +/// \param Filename the file name to adjust. +/// +/// \param isysroot When non-NULL, the PCH file is a relocatable PCH file and +/// the returned filename will be adjusted by this system root. +/// +/// \returns either the original filename (if it needs no adjustment) or the +/// adjusted filename (which points into the @p Filename parameter). +static const char * +adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) { + assert(Filename && "No file name to adjust?"); -/// \brief Write the PCH metadata (e.g., i686-apple-darwin9). -void PCHWriter::WriteMetadata(ASTContext &Context) { - using namespace llvm; + if (!isysroot) + return Filename; - // Original file name - SourceManager &SM = Context.getSourceManager(); - if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { - BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev(); - FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME)); - FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); + // Verify that the filename and the system root have the same prefix. + unsigned Pos = 0; + for (; Filename[Pos] && isysroot[Pos]; ++Pos) + if (Filename[Pos] != isysroot[Pos]) + return Filename; // Prefixes don't match. - llvm::sys::Path MainFilePath(MainFile->getName()); - std::string MainFileName; - - if (!MainFilePath.isAbsolute()) { - llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory(); - P.appendComponent(MainFilePath.toString()); - MainFileName = P.toString(); - } else { - MainFileName = MainFilePath.toString(); - } + // We hit the end of the filename before we hit the end of the system root. + if (!Filename[Pos]) + return Filename; - RecordData Record; - Record.push_back(pch::ORIGINAL_FILE_NAME); - Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileName.c_str(), - MainFileName.size()); - } + // If the file name has a '/' at the current position, skip over the '/'. + // We distinguish sysroot-based includes from absolute includes by the + // absence of '/' at the beginning of sysroot-based includes. + if (Filename[Pos] == '/') + ++Pos; + + return Filename + Pos; +} + +/// \brief Write the PCH metadata (e.g., i686-apple-darwin9). +void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) { + using namespace llvm; // Metadata const TargetInfo &Target = Context.Target; @@ -495,6 +525,7 @@ void PCHWriter::WriteMetadata(ASTContext &Context) { MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor + MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Target triple unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev); @@ -504,8 +535,47 @@ void PCHWriter::WriteMetadata(ASTContext &Context) { Record.push_back(pch::VERSION_MINOR); Record.push_back(CLANG_VERSION_MAJOR); Record.push_back(CLANG_VERSION_MINOR); - const char *Triple = Target.getTargetTriple(); - Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple, strlen(Triple)); + Record.push_back(isysroot != 0); + const std::string &TripleStr = Target.getTriple().getTriple(); + Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, TripleStr); + + // Original file name + SourceManager &SM = Context.getSourceManager(); + if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) { + BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev(); + FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME)); + FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name + unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev); + + llvm::sys::Path MainFilePath(MainFile->getName()); + std::string MainFileName; + + if (!MainFilePath.isAbsolute()) { + llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory(); + P.appendComponent(MainFilePath.str()); + MainFileName = P.str(); + } else { + MainFileName = MainFilePath.str(); + } + + const char *MainFileNameStr = MainFileName.c_str(); + MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr, + isysroot); + RecordData Record; + Record.push_back(pch::ORIGINAL_FILE_NAME); + Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr); + } + + // Subversion branch/version information. + BitCodeAbbrev *SvnAbbrev = new BitCodeAbbrev(); + SvnAbbrev->Add(BitCodeAbbrevOp(pch::SVN_BRANCH_REVISION)); + SvnAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // SVN revision + SvnAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag + unsigned SvnAbbrevCode = Stream.EmitAbbrev(SvnAbbrev); + Record.clear(); + Record.push_back(pch::SVN_BRANCH_REVISION); + Record.push_back(getClangSubversionRevision()); + Stream.EmitRecordWithBlob(SvnAbbrevCode, Record, getClangSubversionPath()); } /// \brief Write the LangOptions structure. @@ -524,11 +594,11 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.CPlusPlus); // C++ Support Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords. - + 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.PascalStrings); // Allow Pascal strings Record.push_back(LangOpts.WritableStrings); // Allow writable strings Record.push_back(LangOpts.LaxVectorConversions); @@ -541,6 +611,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { // Whether static initializers are protected by locks. Record.push_back(LangOpts.ThreadsafeStatics); + Record.push_back(LangOpts.POSIXThreads); Record.push_back(LangOpts.Blocks); // block extension to C Record.push_back(LangOpts.EmitAllDecls); // Emit all declarations, even if // they are unused. @@ -554,7 +625,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { // may be ripped out at any time. Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined. - Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be + Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be // defined. Record.push_back(LangOpts.Static); // Should __STATIC__ be defined (as // opposed to __DYNAMIC__). @@ -569,8 +640,10 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { // unsigned type Record.push_back(LangOpts.getGCMode()); Record.push_back(LangOpts.getVisibilityMode()); + Record.push_back(LangOpts.getStackProtectorMode()); Record.push_back(LangOpts.InstantiationDepth); Record.push_back(LangOpts.OpenCL); + Record.push_back(LangOpts.ElideConstructors); Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record); } @@ -584,15 +657,15 @@ class VISIBILITY_HIDDEN PCHStatCacheTrait { public: typedef const char * key_type; typedef key_type key_type_ref; - + typedef std::pair<int, struct stat> data_type; typedef const data_type& data_type_ref; static unsigned ComputeHash(const char *path) { return BernsteinHash(path); } - - std::pair<unsigned,unsigned> + + std::pair<unsigned,unsigned> EmitKeyDataLength(llvm::raw_ostream& Out, const char *path, data_type_ref Data) { unsigned StrLen = strlen(path); @@ -603,19 +676,19 @@ public: clang::io::Emit8(Out, DataLen); return std::make_pair(StrLen + 1, DataLen); } - + void EmitKey(llvm::raw_ostream& Out, const char *path, unsigned KeyLen) { Out.write(path, KeyLen); } - + void EmitData(llvm::raw_ostream& Out, key_type_ref, data_type_ref Data, unsigned DataLen) { using namespace clang::io; uint64_t Start = Out.tell(); (void)Start; - + // Result of stat() Emit8(Out, Data.first? 1 : 0); - + if (Data.first == 0) { Emit32(Out, (uint32_t) Data.second.st_ino); Emit32(Out, (uint32_t) Data.second.st_dev); @@ -630,18 +703,22 @@ public: } // end anonymous namespace /// \brief Write the stat() system call cache to the PCH file. -void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { +void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls, + const char *isysroot) { // Build the on-disk hash table containing information about every // stat() call. OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator; unsigned NumStatEntries = 0; - for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), + for (MemorizeStatCalls::iterator Stat = StatCalls.begin(), StatEnd = StatCalls.end(); - Stat != StatEnd; ++Stat, ++NumStatEntries) - Generator.insert(Stat->first(), Stat->second); - + Stat != StatEnd; ++Stat, ++NumStatEntries) { + const char *Filename = Stat->first(); + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); + Generator.insert(Filename, Stat->second); + } + // Create the on-disk hash table in a buffer. - llvm::SmallVector<char, 4096> StatCacheData; + llvm::SmallString<4096> StatCacheData; uint32_t BucketOffset; { llvm::raw_svector_ostream Out(StatCacheData); @@ -664,9 +741,7 @@ void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) { Record.push_back(pch::STAT_CACHE); Record.push_back(BucketOffset); Record.push_back(NumStatEntries); - Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, - &StatCacheData.front(), - StatCacheData.size()); + Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str()); } //===----------------------------------------------------------------------===// @@ -734,7 +809,8 @@ static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) { /// errors), we probably won't have to create file entries for any of /// the files in the AST. void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, - const Preprocessor &PP) { + const Preprocessor &PP, + const char *isysroot) { RecordData Record; // Enter the source manager block. @@ -755,21 +831,22 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, for (unsigned I = 0, N = LineTable.getNumFilenames(); I != N; ++I) { // Emit the file name const char *Filename = LineTable.getFilename(I); + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); unsigned FilenameLen = Filename? strlen(Filename) : 0; Record.push_back(FilenameLen); if (FilenameLen) Record.insert(Record.end(), Filename, Filename + FilenameLen); } - + // Emit the line entries for (LineTableInfo::iterator L = LineTable.begin(), LEnd = LineTable.end(); L != LEnd; ++L) { // Emit the file ID Record.push_back(L->first); - + // Emit the line entries Record.push_back(L->second.size()); - for (std::vector<LineEntry>::iterator LE = L->second.begin(), + for (std::vector<LineEntry>::iterator LE = L->second.begin(), LEEnd = L->second.end(); LE != LEEnd; ++LE) { Record.push_back(LE->FileOffset); @@ -783,9 +860,9 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, } // Write out entries for all of the header files we know about. - HeaderSearch &HS = PP.getHeaderSearchInfo(); + HeaderSearch &HS = PP.getHeaderSearchInfo(); Record.clear(); - for (HeaderSearch::header_file_iterator I = HS.header_file_begin(), + for (HeaderSearch::header_file_iterator I = HS.header_file_begin(), E = HS.header_file_end(); I != E; ++I) { Record.push_back(I->isImport); @@ -801,7 +878,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, std::vector<uint32_t> SLocEntryOffsets; RecordData PreloadSLocs; SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1); - for (SourceManager::sloc_entry_iterator + for (SourceManager::sloc_entry_iterator SLoc = SourceMgr.sloc_entry_begin() + 1, SLocEnd = SourceMgr.sloc_entry_end(); SLoc != SLocEnd; ++SLoc) { @@ -831,9 +908,20 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (Content->Entry) { // The source location entry is a file. The blob associated // with this entry is the file name. - Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, - Content->Entry->getName(), - strlen(Content->Entry->getName())); + + // Turn the file name into an absolute path, if it isn't already. + const char *Filename = Content->Entry->getName(); + llvm::sys::Path FilePath(Filename, strlen(Filename)); + std::string FilenameStr; + if (!FilePath.isAbsolute()) { + llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory(); + P.appendComponent(FilePath.str()); + FilenameStr = P.str(); + Filename = FilenameStr.c_str(); + } + + Filename = adjustFilenameForRelocatablePCH(Filename, isysroot); + Stream.EmitRecordWithBlob(SLocFileAbbrv, Record, Filename); // FIXME: For now, preload all file source locations, so that // we get the appropriate File entries in the reader. This is @@ -848,12 +936,13 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // the reader side). const llvm::MemoryBuffer *Buffer = Content->getBuffer(); const char *Name = Buffer->getBufferIdentifier(); - Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, Name, strlen(Name) + 1); + Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, + llvm::StringRef(Name, strlen(Name) + 1)); Record.clear(); Record.push_back(pch::SM_SLOC_BUFFER_BLOB); Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, - Buffer->getBufferStart(), - Buffer->getBufferSize() + 1); + llvm::StringRef(Buffer->getBufferStart(), + Buffer->getBufferSize() + 1)); if (strcmp(Name, "<built-in>") == 0) PreloadSLocs.push_back(SLocEntryOffsets.size()); @@ -889,13 +978,13 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev); - + Record.clear(); Record.push_back(pch::SOURCE_LOCATION_OFFSETS); Record.push_back(SLocEntryOffsets.size()); Record.push_back(SourceMgr.getNextOffset()); Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, - (const char *)&SLocEntryOffsets.front(), + (const char *)&SLocEntryOffsets.front(), SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0])); // Write the source location entry preloads array, telling the PCH @@ -922,12 +1011,12 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { // Enter the preprocessor block. Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2); - + // If the PCH file contains __DATE__ or __TIME__ emit a warning about this. // FIXME: use diagnostics subsystem for localization etc. if (PP.SawDateOrTime()) fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n"); - + // Loop over all the macro definitions that are live at the end of the file, // emitting each to the PP section. for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); @@ -946,13 +1035,13 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { MacroOffsets[I->first] = Stream.GetCurrentBitNo(); Record.push_back(MI->getDefinitionLoc().getRawEncoding()); Record.push_back(MI->isUsed()); - + unsigned Code; if (MI->isObjectLike()) { Code = pch::PP_MACRO_OBJECT_LIKE; } else { Code = pch::PP_MACRO_FUNCTION_LIKE; - + Record.push_back(MI->isC99Varargs()); Record.push_back(MI->isGNUVarargs()); Record.push_back(MI->getNumArgs()); @@ -969,19 +1058,19 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { // tokens in it because they are created by the parser, and thus can't be // in a macro definition. const Token &Tok = MI->getReplacementToken(TokNo); - + Record.push_back(Tok.getLocation().getRawEncoding()); Record.push_back(Tok.getLength()); // FIXME: When reading literal tokens, reconstruct the literal pointer if // it is needed. AddIdentifierRef(Tok.getIdentifierInfo(), Record); - + // FIXME: Should translate token kind to a stable encoding. Record.push_back(Tok.getKind()); // FIXME: Should translate token flags to a stable encoding. Record.push_back(Tok.getFlags()); - + Stream.EmitRecord(pch::PP_TOKEN, Record); Record.clear(); } @@ -992,18 +1081,18 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { void PCHWriter::WriteComments(ASTContext &Context) { using namespace llvm; - + if (Context.Comments.empty()) return; - + BitCodeAbbrev *CommentAbbrev = new BitCodeAbbrev(); CommentAbbrev->Add(BitCodeAbbrevOp(pch::COMMENT_RANGES)); CommentAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned CommentCode = Stream.EmitAbbrev(CommentAbbrev); - + RecordData Record; Record.push_back(pch::COMMENT_RANGES); - Stream.EmitRecordWithBlob(CommentCode, Record, + Stream.EmitRecordWithBlob(CommentCode, Record, (const char*)&Context.Comments[0], Context.Comments.size() * sizeof(SourceRange)); } @@ -1013,11 +1102,11 @@ void PCHWriter::WriteComments(ASTContext &Context) { //===----------------------------------------------------------------------===// /// \brief Write the representation of a type to the PCH stream. -void PCHWriter::WriteType(const Type *T) { +void PCHWriter::WriteType(QualType T) { pch::TypeID &ID = TypeIDs[T]; if (ID == 0) // we haven't seen this type before. ID = NextTypeID++; - + // Record the offset for this type. if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS) TypeOffsets.push_back(Stream.GetCurrentBitNo()); @@ -1027,25 +1116,33 @@ void PCHWriter::WriteType(const Type *T) { } RecordData Record; - + // Emit the type's representation. PCHTypeWriter W(*this, Record); - switch (T->getTypeClass()) { - // For all of the concrete, non-dependent types, call the - // appropriate visitor function. + + if (T.hasNonFastQualifiers()) { + Qualifiers Qs = T.getQualifiers(); + AddTypeRef(T.getUnqualifiedType(), Record); + Record.push_back(Qs.getAsOpaqueValue()); + W.Code = pch::TYPE_EXT_QUAL; + } else { + switch (T->getTypeClass()) { + // For all of the concrete, non-dependent types, call the + // appropriate visitor function. #define TYPE(Class, Base) \ - case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break; + case Type::Class: W.Visit##Class##Type(cast<Class##Type>(T)); break; #define ABSTRACT_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" - // For all of the dependent type nodes (which only occur in C++ - // templates), produce an error. + // For all of the dependent type nodes (which only occur in C++ + // templates), produce an error. #define TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" - assert(false && "Cannot serialize dependent type nodes"); - break; + assert(false && "Cannot serialize dependent type nodes"); + break; + } } // Emit the serialized record. @@ -1062,9 +1159,8 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) { // Emit all of the types that need to be emitted (so far). while (!TypesToEmit.empty()) { - const Type *T = TypesToEmit.front(); + QualType T = TypesToEmit.front(); TypesToEmit.pop(); - assert(!isa<BuiltinType>(T) && "Built-in types are not serialized"); WriteType(T); } @@ -1081,7 +1177,7 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) { /// /// \returns the offset of the DECL_CONTEXT_LEXICAL block within the /// bistream, or 0 if no block was written. -uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context, +uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC) { if (DC->decls_empty()) return 0; @@ -1133,7 +1229,7 @@ uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context, AddDeclarationName(D->first, Record); DeclContext::lookup_result Result = D->second.getLookupResult(Context); Record.push_back(Result.second - Result.first); - for(; Result.first != Result.second; ++Result.first) + for (; Result.first != Result.second; ++Result.first) AddDeclRef(*Result.first, Record); } @@ -1157,12 +1253,12 @@ class VISIBILITY_HIDDEN PCHMethodPoolTrait { public: typedef Selector key_type; typedef key_type key_type_ref; - + typedef std::pair<ObjCMethodList, ObjCMethodList> data_type; typedef const data_type& data_type_ref; explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { } - + static unsigned ComputeHash(Selector Sel) { unsigned N = Sel.getNumArgs(); if (N == 0) @@ -1173,27 +1269,27 @@ public: R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R); return R; } - - std::pair<unsigned,unsigned> + + std::pair<unsigned,unsigned> EmitKeyDataLength(llvm::raw_ostream& Out, Selector Sel, data_type_ref Methods) { unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4); clang::io::Emit16(Out, KeyLen); unsigned DataLen = 2 + 2; // 2 bytes for each of the method counts - for (const ObjCMethodList *Method = &Methods.first; Method; + for (const ObjCMethodList *Method = &Methods.first; Method; Method = Method->Next) if (Method->Method) DataLen += 4; - for (const ObjCMethodList *Method = &Methods.second; Method; + for (const ObjCMethodList *Method = &Methods.second; Method; Method = Method->Next) if (Method->Method) DataLen += 4; clang::io::Emit16(Out, DataLen); return std::make_pair(KeyLen, DataLen); } - + void EmitKey(llvm::raw_ostream& Out, Selector Sel, unsigned) { - uint64_t Start = Out.tell(); + uint64_t Start = Out.tell(); assert((Start >> 32) == 0 && "Selector key offset too large"); Writer.SetSelectorOffset(Sel, Start); unsigned N = Sel.getNumArgs(); @@ -1201,32 +1297,32 @@ public: if (N == 0) N = 1; for (unsigned I = 0; I != N; ++I) - clang::io::Emit32(Out, + clang::io::Emit32(Out, Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I))); } - + void EmitData(llvm::raw_ostream& Out, key_type_ref, data_type_ref Methods, unsigned DataLen) { uint64_t Start = Out.tell(); (void)Start; unsigned NumInstanceMethods = 0; - for (const ObjCMethodList *Method = &Methods.first; Method; + for (const ObjCMethodList *Method = &Methods.first; Method; Method = Method->Next) if (Method->Method) ++NumInstanceMethods; unsigned NumFactoryMethods = 0; - for (const ObjCMethodList *Method = &Methods.second; Method; + for (const ObjCMethodList *Method = &Methods.second; Method; Method = Method->Next) if (Method->Method) ++NumFactoryMethods; clang::io::Emit16(Out, NumInstanceMethods); clang::io::Emit16(Out, NumFactoryMethods); - for (const ObjCMethodList *Method = &Methods.first; Method; + for (const ObjCMethodList *Method = &Methods.first; Method; Method = Method->Next) if (Method->Method) clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); - for (const ObjCMethodList *Method = &Methods.second; Method; + for (const ObjCMethodList *Method = &Methods.second; Method; Method = Method->Next) if (Method->Method) clang::io::Emit32(Out, Writer.getDeclID(Method->Method)); @@ -1248,13 +1344,13 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { bool Empty = true; { OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator; - + // Create the on-disk hash table representation. Start by // iterating through the instance method pool. PCHMethodPoolTrait::key_type Key; unsigned NumSelectorsInMethodPool = 0; for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - Instance = SemaRef.InstanceMethodPool.begin(), + Instance = SemaRef.InstanceMethodPool.begin(), InstanceEnd = SemaRef.InstanceMethodPool.end(); Instance != InstanceEnd; ++Instance) { // Check whether there is a factory method with the same @@ -1264,7 +1360,7 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { if (Factory == SemaRef.FactoryMethodPool.end()) Generator.insert(Instance->first, - std::make_pair(Instance->second, + std::make_pair(Instance->second, ObjCMethodList())); else Generator.insert(Instance->first, @@ -1277,7 +1373,7 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { // Now iterate through the factory method pool, to pick up any // selectors that weren't already in the instance method pool. for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - Factory = SemaRef.FactoryMethodPool.begin(), + Factory = SemaRef.FactoryMethodPool.begin(), FactoryEnd = SemaRef.FactoryMethodPool.end(); Factory != FactoryEnd; ++Factory) { // Check whether there is an instance method with the same @@ -1298,7 +1394,7 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { return; // Create the on-disk hash table in a buffer. - llvm::SmallVector<char, 4096> MethodPool; + llvm::SmallString<4096> MethodPool; uint32_t BucketOffset; SelectorOffsets.resize(SelVector.size()); { @@ -1329,9 +1425,7 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { Record.push_back(pch::METHOD_POOL); Record.push_back(BucketOffset); Record.push_back(NumSelectorsInMethodPool); - Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, - &MethodPool.front(), - MethodPool.size()); + Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str()); // Create a blob abbreviation for the selector table offsets. Abbrev = new BitCodeAbbrev(); @@ -1373,25 +1467,25 @@ class VISIBILITY_HIDDEN PCHIdentifierTableTrait { public: typedef const IdentifierInfo* key_type; typedef key_type key_type_ref; - + typedef pch::IdentID data_type; typedef data_type data_type_ref; - - PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP) + + PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP) : Writer(Writer), PP(PP) { } static unsigned ComputeHash(const IdentifierInfo* II) { return clang::BernsteinHash(II->getName()); } - - std::pair<unsigned,unsigned> - EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II, + + std::pair<unsigned,unsigned> + EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II, pch::IdentID ID) { unsigned KeyLen = strlen(II->getName()) + 1; unsigned DataLen = 4; // 4 bytes for the persistent ID << 1 if (isInterestingIdentifier(II)) { DataLen += 2; // 2 bytes for builtin ID, flags - if (II->hasMacroDefinition() && + if (II->hasMacroDefinition() && !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro()) DataLen += 4; for (IdentifierResolver::iterator D = IdentifierResolver::begin(II), @@ -1406,16 +1500,16 @@ public: clang::io::Emit16(Out, KeyLen); return std::make_pair(KeyLen, DataLen); } - - void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II, + + void EmitKey(llvm::raw_ostream& Out, const IdentifierInfo* II, unsigned KeyLen) { // Record the location of the key data. This is used when generating // the mapping from persistent IDs to strings. Writer.SetIdentifierOffset(II, Out.tell()); Out.write(II->getName(), KeyLen); } - - void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II, + + void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II, pch::IdentID ID, unsigned) { if (!isInterestingIdentifier(II)) { clang::io::Emit32(Out, ID << 1); @@ -1424,8 +1518,8 @@ public: clang::io::Emit32(Out, (ID << 1) | 0x01); uint32_t Bits = 0; - bool hasMacroDefinition = - II->hasMacroDefinition() && + bool hasMacroDefinition = + II->hasMacroDefinition() && !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro(); Bits = (uint32_t)II->getObjCOrBuiltinID(); Bits = (Bits << 1) | hasMacroDefinition; @@ -1443,7 +1537,7 @@ public: // "stat"), but IdentifierResolver::AddDeclToIdentifierChain() // adds declarations to the end of the list (so we need to see the // struct "status" before the function "status"). - llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), + llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II), IdentifierResolver::end()); for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(), DEnd = Decls.rend(); @@ -1465,7 +1559,7 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { // strings. { OnDiskChainedHashTableGenerator<PCHIdentifierTableTrait> Generator; - + // Look for any identifiers that were named while processing the // headers, but are otherwise not needed. We add these to the hash // table to enable checking of the predefines buffer in the case @@ -1486,7 +1580,7 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { } // Create the on-disk hash table in a buffer. - llvm::SmallVector<char, 4096> IdentifierTable; + llvm::SmallString<4096> IdentifierTable; uint32_t BucketOffset; { PCHIdentifierTableTrait Trait(*this, PP); @@ -1507,9 +1601,7 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { RecordData Record; Record.push_back(pch::IDENTIFIER_TABLE); Record.push_back(BucketOffset); - Stream.EmitRecordWithBlob(IDTableAbbrev, Record, - &IdentifierTable.front(), - IdentifierTable.size()); + Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); } // Write the offsets table for identifier IDs. @@ -1548,7 +1640,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::AlwaysInline: break; - + case Attr::AnalyzerNoReturn: break; @@ -1607,13 +1699,14 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { Record.push_back(Sentinel->getNullPos()); break; } - + case Attr::GNUInline: case Attr::IBOutletKind: + case Attr::Malloc: + case Attr::NoDebug: case Attr::NoReturn: case Attr::NoThrow: - case Attr::Nodebug: - case Attr::Noinline: + case Attr::NoInline: break; case Attr::NonNull: { @@ -1630,8 +1723,11 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::Overloadable: break; + case Attr::PragmaPack: + Record.push_back(cast<PragmaPackAttr>(Attr)->getAlignment()); + break; + case Attr::Packed: - Record.push_back(cast<PackedAttr>(Attr)->getAlignment()); break; case Attr::Pure: @@ -1640,7 +1736,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::Regparm: Record.push_back(cast<RegparmAttr>(Attr)->getNumParams()); break; - + case Attr::ReqdWorkGroupSize: Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim()); Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim()); @@ -1660,7 +1756,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::Visibility: // FIXME: stable encoding - Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility()); + Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility()); break; case Attr::WarnUnusedResult: @@ -1692,12 +1788,13 @@ void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { SelectorOffsets[ID - 1] = Offset; } -PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream) - : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS), +PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream) + : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) { } -void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { +void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, + const char *isysroot) { using namespace llvm; ASTContext &Context = SemaRef.Context; @@ -1708,7 +1805,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { Stream.Emit((unsigned)'P', 8); Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'H', 8); - + WriteBlockInfoBlock(); // The translation unit is the first declaration we'll emit. @@ -1726,20 +1823,23 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { getIdentifierRef(&Table.get(BuiltinNames[I])); } - // Build a record containing all of the tentative definitions in - // this header file. Generally, this record will be empty. + // Build a record containing all of the tentative definitions in this file, in + // TentativeDefinitionList order. Generally, this record will be empty for + // headers. RecordData TentativeDefinitions; - for (llvm::DenseMap<DeclarationName, VarDecl *>::iterator - TD = SemaRef.TentativeDefinitions.begin(), - TDEnd = SemaRef.TentativeDefinitions.end(); - TD != TDEnd; ++TD) - AddDeclRef(TD->second, 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); + } // Build a record containing all of the locally-scoped external // declarations in this header file. Generally, this record will be // empty. RecordData LocallyScopedExternalDecls; - for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator + // FIXME: This is filling in the PCH file in densemap order which is + // nondeterminstic! + for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator TD = SemaRef.LocallyScopedExternalDecls.begin(), TDEnd = SemaRef.LocallyScopedExternalDecls.end(); TD != TDEnd; ++TD) @@ -1750,23 +1850,33 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls); - // Build a record containing all of the Objective-C category - // implementations. - RecordData ObjCCategoryImpls; - for (unsigned I = 0, N = SemaRef.ObjCCategoryImpls.size(); I != N; ++I) - AddDeclRef(SemaRef.ObjCCategoryImpls[I], ObjCCategoryImpls); - // Write the remaining PCH contents. RecordData Record; Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4); - WriteMetadata(Context); + WriteMetadata(Context, isysroot); WriteLanguageOptions(Context.getLangOptions()); - if (StatCalls) - WriteStatCache(*StatCalls); - WriteSourceManagerBlock(Context.getSourceManager(), PP); + if (StatCalls && !isysroot) + WriteStatCache(*StatCalls, isysroot); + WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); WritePreprocessor(PP); - WriteComments(Context); - + WriteComments(Context); + // Write the record of special types. + Record.clear(); + + AddTypeRef(Context.getBuiltinVaListType(), Record); + AddTypeRef(Context.getObjCIdType(), Record); + AddTypeRef(Context.getObjCSelType(), Record); + AddTypeRef(Context.getObjCProtoType(), Record); + AddTypeRef(Context.getObjCClassType(), Record); + AddTypeRef(Context.getRawCFConstantStringType(), Record); + AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record); + AddTypeRef(Context.getFILEType(), Record); + AddTypeRef(Context.getjmp_bufType(), Record); + AddTypeRef(Context.getsigjmp_bufType(), Record); + AddTypeRef(Context.ObjCIdRedefinitionType, Record); + AddTypeRef(Context.ObjCClassRedefinitionType, Record); + Stream.EmitRecord(pch::SPECIAL_TYPES, Record); + // Keep writing types and declarations until all types and // declarations have been written. do { @@ -1789,9 +1899,9 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { Record.push_back(pch::TYPE_OFFSET); Record.push_back(TypeOffsets.size()); Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, - (const char *)&TypeOffsets.front(), + (const char *)&TypeOffsets.front(), TypeOffsets.size() * sizeof(TypeOffsets[0])); - + // Write the declaration offsets array Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET)); @@ -1802,20 +1912,9 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { Record.push_back(pch::DECL_OFFSET); Record.push_back(DeclOffsets.size()); Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, - (const char *)&DeclOffsets.front(), + (const char *)&DeclOffsets.front(), DeclOffsets.size() * sizeof(DeclOffsets[0])); - // Write the record of special types. - Record.clear(); - AddTypeRef(Context.getBuiltinVaListType(), Record); - AddTypeRef(Context.getObjCIdType(), Record); - AddTypeRef(Context.getObjCSelType(), Record); - AddTypeRef(Context.getObjCProtoType(), Record); - AddTypeRef(Context.getObjCClassType(), Record); - AddTypeRef(Context.getRawCFConstantStringType(), Record); - AddTypeRef(Context.getRawObjCFastEnumerationStateType(), Record); - Stream.EmitRecord(pch::SPECIAL_TYPES, Record); - // Write the record containing external, unnamed definitions. if (!ExternalDefinitions.empty()) Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions); @@ -1826,17 +1925,13 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { // Write the record containing locally-scoped external definitions. if (!LocallyScopedExternalDecls.empty()) - Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS, + Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS, LocallyScopedExternalDecls); // Write the record containing ext_vector type names. if (!ExtVectorDecls.empty()) Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls); - // Write the record containing Objective-C category implementations. - if (!ObjCCategoryImpls.empty()) - Stream.EmitRecord(pch::OBJC_CATEGORY_IMPLEMENTATIONS, ObjCCategoryImpls); - // Some simple statistics Record.clear(); Record.push_back(NumStatements); @@ -1902,6 +1997,26 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { return; } + unsigned FastQuals = T.getFastQualifiers(); + T.removeFastQualifiers(); + + if (T.hasNonFastQualifiers()) { + pch::TypeID &ID = TypeIDs[T]; + if (ID == 0) { + // We haven't seen these qualifiers applied to this type before. + // Assign it a new ID. This is the only time we enqueue a + // qualified type, and it has no CV qualifiers. + ID = NextTypeID++; + TypesToEmit.push(T); + } + + // Encode the type qualifiers in the type reference. + Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); + return; + } + + assert(!T.hasQualifiers()); + if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) { pch::TypeID ID = 0; switch (BT->getKind()) { @@ -1926,27 +2041,31 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break; case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break; case BuiltinType::NullPtr: ID = pch::PREDEF_TYPE_NULLPTR_ID; break; + case BuiltinType::Char16: ID = pch::PREDEF_TYPE_CHAR16_ID; break; + case BuiltinType::Char32: ID = pch::PREDEF_TYPE_CHAR32_ID; break; case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break; case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break; + case BuiltinType::ObjCId: ID = pch::PREDEF_TYPE_OBJC_ID; break; + case BuiltinType::ObjCClass: ID = pch::PREDEF_TYPE_OBJC_CLASS; break; case BuiltinType::UndeducedAuto: assert(0 && "Should not see undeduced auto here"); break; } - Record.push_back((ID << 3) | T.getCVRQualifiers()); + Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); return; } - pch::TypeID &ID = TypeIDs[T.getTypePtr()]; + pch::TypeID &ID = TypeIDs[T]; if (ID == 0) { // We haven't seen this type before. Assign it a new ID and put it - // into the queu of types to emit. + // into the queue of types to emit. ID = NextTypeID++; - TypesToEmit.push(T.getTypePtr()); + TypesToEmit.push(T); } // Encode the type qualifiers in the type reference. - Record.push_back((ID << 3) | T.getCVRQualifiers()); + Record.push_back((ID << Qualifiers::FastWidth) | FastQuals); } void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) { @@ -1956,7 +2075,7 @@ void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) { } pch::DeclID &ID = DeclIDs[D]; - if (ID == 0) { + if (ID == 0) { // We haven't seen this declaration before. Give it a new ID and // enqueue it in the list of declarations to emit. ID = DeclIDs.size(); diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index a6843e1b9efd..4527bb1f9010 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -14,7 +14,10 @@ #include "clang/Frontend/PCHWriter.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" +#include "clang/AST/TypeLocVisitor.h" #include "llvm/Bitcode/BitstreamWriter.h" +#include <cstdio> + using namespace clang; //===----------------------------------------------------------------------===// @@ -32,8 +35,8 @@ namespace { pch::DeclCode Code; unsigned AbbrevToUse; - PCHDeclWriter(PCHWriter &Writer, ASTContext &Context, - PCHWriter::RecordData &Record) + PCHDeclWriter(PCHWriter &Writer, ASTContext &Context, + PCHWriter::RecordData &Record) : Writer(Writer), Context(Context), Record(Record) { } @@ -47,6 +50,7 @@ namespace { void VisitRecordDecl(RecordDecl *D); void VisitValueDecl(ValueDecl *D); void VisitEnumConstantDecl(EnumConstantDecl *D); + void VisitDeclaratorDecl(DeclaratorDecl *D); void VisitFunctionDecl(FunctionDecl *D); void VisitFieldDecl(FieldDecl *D); void VisitVarDecl(VarDecl *D); @@ -55,7 +59,7 @@ namespace { void VisitOriginalParmVarDecl(OriginalParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); void VisitBlockDecl(BlockDecl *D); - void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, + void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, uint64_t VisibleOffset); void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCContainerDecl(ObjCContainerDecl *D); @@ -109,9 +113,12 @@ void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) { void PCHDeclWriter::VisitTagDecl(TagDecl *D) { VisitTypeDecl(D); + Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding Record.push_back(D->isDefinition()); Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); + Writer.AddSourceLocation(D->getRBraceLoc(), Record); + Writer.AddSourceLocation(D->getTagKeywordLoc(), Record); } void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) { @@ -125,6 +132,7 @@ void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) { VisitTagDecl(D); Record.push_back(D->hasFlexibleArrayMember()); Record.push_back(D->isAnonymousStructOrUnion()); + Record.push_back(D->hasObjectMember()); Code = pch::DECL_RECORD; } @@ -141,22 +149,99 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { Writer.AddAPSInt(D->getInitVal(), Record); Code = pch::DECL_ENUM_CONSTANT; } +namespace { -void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { +class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { + PCHWriter &Writer; + PCHWriter::RecordData &Record; + +public: + TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) + : Writer(Writer), Record(Record) { } + +#define ABSTRACT_TYPELOC(CLASS) +#define TYPELOC(CLASS, PARENT, TYPE) \ + void Visit##CLASS(CLASS TyLoc); +#include "clang/AST/TypeLocNodes.def" + + void VisitTypeLoc(TypeLoc TyLoc) { + assert(0 && "A type loc wrapper was not handled!"); + } +}; + +} + +void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getStartLoc(), Record); +} +void TypeLocWriter::VisitTypedefLoc(TypedefLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getNameLoc(), Record); +} +void TypeLocWriter::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getNameLoc(), Record); +} +void TypeLocWriter::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getLAngleLoc(), Record); + Writer.AddSourceLocation(TyLoc.getRAngleLoc(), Record); + for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i) + Writer.AddSourceLocation(TyLoc.getProtocolLoc(i), Record); +} +void TypeLocWriter::VisitPointerLoc(PointerLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getStarLoc(), Record); +} +void TypeLocWriter::VisitBlockPointerLoc(BlockPointerLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getCaretLoc(), Record); +} +void TypeLocWriter::VisitMemberPointerLoc(MemberPointerLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getStarLoc(), Record); +} +void TypeLocWriter::VisitReferenceLoc(ReferenceLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getAmpLoc(), Record); +} +void TypeLocWriter::VisitFunctionLoc(FunctionLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getLParenLoc(), Record); + Writer.AddSourceLocation(TyLoc.getRParenLoc(), Record); + for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i) + Writer.AddDeclRef(TyLoc.getArg(i), Record); +} +void TypeLocWriter::VisitArrayLoc(ArrayLoc TyLoc) { + Writer.AddSourceLocation(TyLoc.getLBracketLoc(), Record); + Writer.AddSourceLocation(TyLoc.getRBracketLoc(), Record); + Record.push_back(TyLoc.getSizeExpr() ? 1 : 0); + if (TyLoc.getSizeExpr()) + Writer.AddStmt(TyLoc.getSizeExpr()); +} + +void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { VisitValueDecl(D); + DeclaratorInfo *DInfo = D->getDeclaratorInfo(); + if (DInfo == 0) { + Writer.AddTypeRef(QualType(), Record); + return; + } + + Writer.AddTypeRef(DInfo->getTypeLoc().getSourceType(), Record); + TypeLocWriter TLW(Writer, Record); + for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) + TLW.Visit(TL); +} + +void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { + VisitDeclaratorDecl(D); Record.push_back(D->isThisDeclarationADefinition()); if (D->isThisDeclarationADefinition()) Writer.AddStmt(D->getBody()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->isInline()); - Record.push_back(D->isC99InlineDefinition()); Record.push_back(D->isVirtualAsWritten()); Record.push_back(D->isPure()); Record.push_back(D->hasInheritedPrototype()); Record.push_back(D->hasWrittenPrototype()); Record.push_back(D->isDeleted()); - Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record); + Record.push_back(D->isTrivial()); + Record.push_back(D->isCopyAssignment()); + Record.push_back(D->hasImplicitReturnZero()); Writer.AddSourceLocation(D->getLocEnd(), Record); // FIXME: C++ TemplateOrInstantiation Record.push_back(D->param_size()); @@ -169,7 +254,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { VisitNamedDecl(D); // FIXME: convert to LazyStmtPtr? - // Unlike C/C++, method bodies will never be in header files. + // Unlike C/C++, method bodies will never be in header files. Record.push_back(D->getBody() != 0); if (D->getBody() != 0) { Writer.AddStmt(D->getBody()); @@ -180,13 +265,13 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Record.push_back(D->isVariadic()); Record.push_back(D->isSynthesized()); // FIXME: stable encoding for @required/@optional - Record.push_back(D->getImplementationControl()); + Record.push_back(D->getImplementationControl()); // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway - Record.push_back(D->getObjCDeclQualifier()); + Record.push_back(D->getObjCDeclQualifier()); Writer.AddTypeRef(D->getResultType(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->param_size()); - for (ObjCMethodDecl::param_iterator P = D->param_begin(), + for (ObjCMethodDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); P != PEnd; ++P) Writer.AddDeclRef(*P, Record); Code = pch::DECL_OBJC_METHOD; @@ -203,12 +288,12 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); Writer.AddDeclRef(D->getSuperClass(), Record); Record.push_back(D->protocol_size()); - for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), + for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), PEnd = D->protocol_end(); P != PEnd; ++P) Writer.AddDeclRef(*P, Record); Record.push_back(D->ivar_size()); - for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), + for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), IEnd = D->ivar_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Writer.AddDeclRef(D->getCategoryList(), Record); @@ -223,7 +308,7 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { VisitFieldDecl(D); // FIXME: stable encoding for @public/@private/@protected/@package - Record.push_back(D->getAccessControl()); + Record.push_back(D->getAccessControl()); Code = pch::DECL_OBJC_IVAR; } @@ -232,7 +317,7 @@ void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Record.push_back(D->isForwardDecl()); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Code = pch::DECL_OBJC_PROTOCOL; @@ -254,7 +339,7 @@ void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) { void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { VisitDecl(D); Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Code = pch::DECL_OBJC_FORWARD_PROTOCOL; @@ -264,7 +349,7 @@ void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { VisitObjCContainerDecl(D); Writer.AddDeclRef(D->getClassInterface(), Record); Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Writer.AddDeclRef(D->getNextClassCategory(), Record); @@ -294,9 +379,8 @@ void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { } void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { - VisitNamedDecl(D); + VisitObjCContainerDecl(D); Writer.AddDeclRef(D->getClassInterface(), Record); - Writer.AddSourceLocation(D->getLocEnd(), Record); // Abstract class (no need to define a stable pch::DECL code). } @@ -321,7 +405,7 @@ void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { } void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { - VisitValueDecl(D); + VisitDeclaratorDecl(D); Record.push_back(D->isMutable()); Record.push_back(D->getBitWidth()? 1 : 0); if (D->getBitWidth()) @@ -330,13 +414,12 @@ void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) { } void PCHDeclWriter::VisitVarDecl(VarDecl *D) { - VisitValueDecl(D); + VisitDeclaratorDecl(D); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->isThreadSpecified()); Record.push_back(D->hasCXXDirectInitializer()); Record.push_back(D->isDeclaredInCondition()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); - Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record); Record.push_back(D->getInit()? 1 : 0); if (D->getInit()) Writer.AddStmt(D->getInit()); @@ -351,16 +434,14 @@ void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { VisitVarDecl(D); Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding - // FIXME: emit default argument (C++) - // FIXME: why isn't the "default argument" just stored as the initializer - // in VarDecl? Code = pch::DECL_PARM_VAR; - - + + // If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here // we dynamically check for the properties that we optimize for, but don't // know are true of all PARM_VAR_DECLs. - if (!D->hasAttrs() && + if (!D->getDeclaratorInfo() && + !D->hasAttrs() && !D->isImplicit() && !D->isUsed() && D->getAccess() == AS_none && @@ -413,7 +494,7 @@ void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) { /// that there are no declarations visible from this context. Note /// that this value will not be emitted for non-primary declaration /// contexts. -void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, +void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, uint64_t VisibleOffset) { Record.push_back(LexicalOffset); Record.push_back(VisibleOffset); @@ -439,26 +520,90 @@ void PCHWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isImplicit Abv->Add(BitCodeAbbrevOp(0)); // isUsed Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier - + // NamedDecl Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name // ValueDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type + // DeclaratorDecl + Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType // VarDecl Abv->Add(BitCodeAbbrevOp(0)); // StorageClass Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer Abv->Add(BitCodeAbbrevOp(0)); // isDeclaredInCondition Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeSpecStartLoc Abv->Add(BitCodeAbbrevOp(0)); // HasInit // ParmVarDecl Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier - + ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv); } +/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by +/// consumers of the AST. +/// +/// Such decls will always be deserialized from the PCH file, so we would like +/// this to be as restrictive as possible. Currently the predicate is driven by +/// code generation requirements, if other clients have a different notion of +/// what is "required" then we may have to consider an alternate scheme where +/// clients can iterate over the top-level decls and get information on them, +/// without necessary deserializing them. We could explicitly require such +/// clients to use a separate API call to "realize" the decl. This should be +/// relatively painless since they would presumably only do it for top-level +/// decls. +// +// FIXME: This predicate is essentially IRgen's predicate to determine whether a +// declaration can be deferred. Merge them somehow. +static bool isRequiredDecl(const Decl *D, ASTContext &Context) { + // File scoped assembly must be seen. + if (isa<FileScopeAsmDecl>(D)) + return true; + + // Otherwise if this isn't a function or a file scoped variable it doesn't + // need to be seen. + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (!VD->isFileVarDecl()) + return false; + } else if (!isa<FunctionDecl>(D)) + return false; + + // Aliases and used decls must be seen. + if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>()) + return true; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // Forward declarations don't need to be seen. + if (!FD->isThisDeclarationADefinition()) + return false; + + // Constructors and destructors must be seen. + if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) + return true; + + // Otherwise, this is required unless it is static. + // + // FIXME: Inlines. + return FD->getStorageClass() != FunctionDecl::Static; + } else { + const VarDecl *VD = cast<VarDecl>(D); + + // In C++, this doesn't need to be seen if it is marked "extern". + if (Context.getLangOptions().CPlusPlus && !VD->getInit() && + (VD->getStorageClass() == VarDecl::Extern || + VD->isExternC())) + return false; + + // In C, this doesn't need to be seen unless it is a definition. + if (!Context.getLangOptions().CPlusPlus && !VD->getInit()) + return false; + + // Otherwise, this is required unless it is static. + return VD->getStorageClass() != VarDecl::Static; + } +} + /// \brief Write a block containing all of the declarations. void PCHWriter::WriteDeclsBlock(ASTContext &Context) { // Enter the declarations block. @@ -466,7 +611,7 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { // Output the abbreviations that we will use in this block. WriteDeclsBlockAbbrevs(); - + // Emit all of the declarations. RecordData Record; PCHDeclWriter W(*this, Context, Record); @@ -517,17 +662,19 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { exit(-1); } Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); - + // If the declaration had any attributes, write them now. if (D->hasAttrs()) WriteAttributeRecord(D->getAttrs()); // Flush any expressions that were written as part of this declaration. FlushStmts(); - - // Note external declarations so that we can add them to a record - // in the PCH file later. - if (isa<FileScopeAsmDecl>(D)) + + // Note "external" declarations so that we can add them to a record in the + // PCH file later. + // + // FIXME: This should be renamed, the predicate is much more complicated. + if (isRequiredDecl(D, Context)) ExternalDefinitions.push_back(ID); } diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 5235326e9ffd..9497f973f6bc 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/PCHWriter.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/StmtVisitor.h" #include "llvm/Bitcode/BitstreamWriter.h" @@ -86,7 +87,7 @@ namespace { void VisitShuffleVectorExpr(ShuffleVectorExpr *E); void VisitBlockExpr(BlockExpr *E); void VisitBlockDeclRefExpr(BlockDeclRefExpr *E); - + // Objective-C Expressions void VisitObjCStringLiteral(ObjCStringLiteral *E); void VisitObjCEncodeExpr(ObjCEncodeExpr *E); @@ -94,21 +95,27 @@ namespace { void VisitObjCProtocolExpr(ObjCProtocolExpr *E); void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E); void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E); - void VisitObjCKVCRefExpr(ObjCKVCRefExpr *E); + void VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *E); void VisitObjCMessageExpr(ObjCMessageExpr *E); void VisitObjCSuperExpr(ObjCSuperExpr *E); - - // Objective-C Statements + void VisitObjCIsaExpr(ObjCIsaExpr *E); + + // Objective-C Statements void VisitObjCForCollectionStmt(ObjCForCollectionStmt *); void VisitObjCAtCatchStmt(ObjCAtCatchStmt *); void VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *); void VisitObjCAtTryStmt(ObjCAtTryStmt *); void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); + + // C++ Statements + void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); + void VisitCXXConstructExpr(CXXConstructExpr *E); }; } -void PCHStmtWriter::VisitStmt(Stmt *S) { +void PCHStmtWriter::VisitStmt(Stmt *S) { } void PCHStmtWriter::VisitNullStmt(NullStmt *S) { @@ -176,7 +183,7 @@ void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) { Writer.WriteSubStmt(S->getCond()); Writer.WriteSubStmt(S->getBody()); Writer.AddSourceLocation(S->getSwitchLoc(), Record); - for (SwitchCase *SC = S->getSwitchCaseList(); SC; + for (SwitchCase *SC = S->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) Record.push_back(Writer.getSwitchCaseID(SC)); Code = pch::STMT_SWITCH; @@ -340,7 +347,7 @@ void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) { // StringLiteral. However, we can't do so now because we have no // provision for coping with abbreviations when we're jumping around // the PCH file during deserialization. - Record.insert(Record.end(), + Record.insert(Record.end(), E->getStrData(), E->getStrData() + E->getByteLength()); for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I) Writer.AddSourceLocation(E->getStrTokenLoc(I), Record); @@ -350,7 +357,7 @@ void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) { void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) { VisitExpr(E); Record.push_back(E->getValue()); - Writer.AddSourceLocation(E->getLoc(), Record); + Writer.AddSourceLocation(E->getLocation(), Record); Record.push_back(E->isWide()); Code = pch::EXPR_CHARACTER_LITERAL; } @@ -371,7 +378,7 @@ void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) { Code = pch::EXPR_UNARY_OPERATOR; } -void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { +void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { VisitExpr(E); Record.push_back(E->isSizeOf()); if (E->isArgumentType()) @@ -410,12 +417,23 @@ void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) { Writer.AddDeclRef(E->getMemberDecl(), Record); Writer.AddSourceLocation(E->getMemberLoc(), Record); Record.push_back(E->isArrow()); + // FIXME: C++ nested-name-specifier + // FIXME: C++ template argument list Code = pch::EXPR_MEMBER; } +void PCHStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) { + VisitExpr(E); + Writer.WriteSubStmt(E->getBase()); + Writer.AddSourceLocation(E->getIsaMemberLoc(), Record); + Record.push_back(E->isArrow()); + Code = pch::EXPR_OBJC_ISA; +} + void PCHStmtWriter::VisitCastExpr(CastExpr *E) { VisitExpr(E); Writer.WriteSubStmt(E->getSubExpr()); + Record.push_back(E->getCastKind()); // FIXME: stable encoding } void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) { @@ -439,6 +457,8 @@ void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) { Writer.WriteSubStmt(E->getCond()); Writer.WriteSubStmt(E->getLHS()); Writer.WriteSubStmt(E->getRHS()); + Writer.AddSourceLocation(E->getQuestionLoc(), Record); + Writer.AddSourceLocation(E->getColonLoc(), Record); Code = pch::EXPR_CONDITIONAL_OPERATOR; } @@ -617,7 +637,7 @@ void PCHStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) { Code = pch::EXPR_OBJC_STRING_LITERAL; } -void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { +void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { VisitExpr(E); Writer.AddTypeRef(E->getEncodedType(), Record); Writer.AddSourceLocation(E->getAtLoc(), Record); @@ -659,13 +679,14 @@ void PCHStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { Code = pch::EXPR_OBJC_PROPERTY_REF_EXPR; } -void PCHStmtWriter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { +void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *E) { VisitExpr(E); Writer.AddDeclRef(E->getGetterMethod(), Record); Writer.AddDeclRef(E->getSetterMethod(), Record); - - // NOTE: ClassProp and Base are mutually exclusive. - Writer.AddDeclRef(E->getClassProp(), Record); + + // NOTE: InterfaceDecl and Base are mutually exclusive. + Writer.AddDeclRef(E->getInterfaceDecl(), Record); Writer.WriteSubStmt(E->getBase()); Writer.AddSourceLocation(E->getLocation(), Record); Writer.AddSourceLocation(E->getClassLoc(), Record); @@ -746,11 +767,31 @@ void PCHStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { } //===----------------------------------------------------------------------===// +// C++ Expressions and Statements. +//===----------------------------------------------------------------------===// + +void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + VisitCallExpr(E); + Record.push_back(E->getOperator()); + Code = pch::EXPR_CXX_OPERATOR_CALL; +} + +void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { + VisitExpr(E); + Writer.AddDeclRef(E->getConstructor(), Record); + Record.push_back(E->isElidable()); + Record.push_back(E->getNumArgs()); + for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) + Writer.WriteSubStmt(E->getArg(I)); + Code = pch::EXPR_CXX_CONSTRUCT; +} + +//===----------------------------------------------------------------------===// // PCHWriter Implementation //===----------------------------------------------------------------------===// unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && + assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() && "SwitchCase recorded twice"); unsigned NextID = SwitchCaseIDs.size(); SwitchCaseIDs[S] = NextID; @@ -758,7 +799,7 @@ unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) { } unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) { - assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && + assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() && "SwitchCase hasn't been seen yet"); return SwitchCaseIDs[S]; } @@ -769,7 +810,7 @@ unsigned PCHWriter::GetLabelID(LabelStmt *S) { std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S); if (Pos != LabelIDs.end()) return Pos->second; - + unsigned NextID = LabelIDs.size(); LabelIDs[S] = NextID; return NextID; @@ -781,17 +822,17 @@ void PCHWriter::WriteSubStmt(Stmt *S) { RecordData Record; PCHStmtWriter Writer(*this, Record); ++NumStatements; - + if (!S) { Stream.EmitRecord(pch::STMT_NULL_PTR, Record); return; } - + Writer.Code = pch::STMT_NULL_PTR; Writer.Visit(S); - assert(Writer.Code != pch::STMT_NULL_PTR && + assert(Writer.Code != pch::STMT_NULL_PTR && "Unhandled expression writing PCH file"); - Stream.EmitRecord(Writer.Code, Record); + Stream.EmitRecord(Writer.Code, Record); } /// \brief Flush all of the statements that have been added to the @@ -799,31 +840,31 @@ void PCHWriter::WriteSubStmt(Stmt *S) { void PCHWriter::FlushStmts() { RecordData Record; PCHStmtWriter Writer(*this, Record); - + for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) { ++NumStatements; Stmt *S = StmtsToEmit[I]; - + if (!S) { Stream.EmitRecord(pch::STMT_NULL_PTR, Record); continue; } - + Writer.Code = pch::STMT_NULL_PTR; Writer.Visit(S); - assert(Writer.Code != pch::STMT_NULL_PTR && + assert(Writer.Code != pch::STMT_NULL_PTR && "Unhandled expression writing PCH file"); - Stream.EmitRecord(Writer.Code, Record); - - assert(N == StmtsToEmit.size() && + Stream.EmitRecord(Writer.Code, Record); + + assert(N == StmtsToEmit.size() && "Substatement writen via AddStmt rather than WriteSubStmt!"); - + // Note that we are at the end of a full expression. Any // expression records that follow this one are part of a different // expression. Record.clear(); Stream.EmitRecord(pch::STMT_STOP, Record); } - + StmtsToEmit.clear(); } diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp index 387ed45a9c71..a83dca0a5ffa 100644 --- a/lib/Frontend/PlistDiagnostics.cpp +++ b/lib/Frontend/PlistDiagnostics.cpp @@ -37,26 +37,44 @@ namespace { std::vector<const PathDiagnostic*> BatchedDiags; const std::string OutputFile; const LangOptions &LangOpts; + llvm::OwningPtr<PathDiagnosticClientFactory> PF; + llvm::OwningPtr<PathDiagnosticClient> SubPDC; + llvm::SmallVector<std::string, 1> FilesMade; public: - PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts); + PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts, + PathDiagnosticClientFactory *pf); ~PlistDiagnostics(); void HandlePathDiagnostic(const PathDiagnostic* D); - - PathGenerationScheme getGenerationScheme() const { return Extensive; } + + PathGenerationScheme getGenerationScheme() const; bool supportsLogicalOpControlFlow() const { return true; } bool supportsAllBlockEdges() const { return true; } virtual bool useVerboseDescription() const { return false; } - }; + }; } // end anonymous namespace PlistDiagnostics::PlistDiagnostics(const std::string& output, - const LangOptions &LO) - : OutputFile(output), LangOpts(LO) {} + const LangOptions &LO, + PathDiagnosticClientFactory *pf) + : OutputFile(output), LangOpts(LO), PF(pf) { + + if (PF) + SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade)); +} PathDiagnosticClient* clang::CreatePlistDiagnosticClient(const std::string& s, - Preprocessor *PP, PreprocessorFactory*) { - return new PlistDiagnostics(s, PP->getLangOptions()); + Preprocessor *PP, PreprocessorFactory*, + PathDiagnosticClientFactory *PF) { + return new PlistDiagnostics(s, PP->getLangOptions(), PF); +} + +PathDiagnosticClient::PathGenerationScheme +PlistDiagnostics::getGenerationScheme() const { + if (const PathDiagnosticClient *PD = SubPDC.get()) + return PD->getGenerationScheme(); + + return Extensive; } static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V, @@ -92,7 +110,7 @@ static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM, // Add in the length of the token, so that we cover multi-char tokens. unsigned offset = extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0; - + Indent(o, indent) << "<dict>\n"; Indent(o, indent) << " <key>line</key><integer>" << Loc.getInstantiationLineNumber() << "</integer>\n"; @@ -115,7 +133,7 @@ static void EmitRange(llvm::raw_ostream& o, const SourceManager &SM, PathDiagnosticRange R, const FIDMap &FM, unsigned indent) { Indent(o, indent) << "<array>\n"; - EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1); + EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1); EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, !R.isPoint); Indent(o, indent) << "</array>\n"; } @@ -144,12 +162,12 @@ static void ReportControlFlow(llvm::raw_ostream& o, const SourceManager &SM, const LangOptions &LangOpts, unsigned indent) { - + Indent(o, indent) << "<dict>\n"; ++indent; - + Indent(o, indent) << "<key>kind</key><string>control</string>\n"; - + // Emit edges. Indent(o, indent) << "<key>edges</key>\n"; ++indent; @@ -169,39 +187,39 @@ static void ReportControlFlow(llvm::raw_ostream& o, --indent; Indent(o, indent) << "</array>\n"; --indent; - + // Output any helper text. const std::string& s = P.getString(); if (!s.empty()) { Indent(o, indent) << "<key>alternate</key>"; EmitString(o, s) << '\n'; } - + --indent; - Indent(o, indent) << "</dict>\n"; + Indent(o, indent) << "</dict>\n"; } -static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P, +static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P, const FIDMap& FM, const SourceManager &SM, const LangOptions &LangOpts, unsigned indent) { - + Indent(o, indent) << "<dict>\n"; ++indent; Indent(o, indent) << "<key>kind</key><string>event</string>\n"; - + // Output the location. FullSourceLoc L = P.getLocation().asLocation(); - + Indent(o, indent) << "<key>location</key>\n"; EmitLocation(o, SM, LangOpts, L, FM, indent); - + // Output the ranges (if any). PathDiagnosticPiece::range_iterator RI = P.ranges_begin(), RE = P.ranges_end(); - + if (RI != RE) { Indent(o, indent) << "<key>ranges</key>\n"; Indent(o, indent) << "<array>\n"; @@ -211,13 +229,13 @@ static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P, --indent; Indent(o, indent) << "</array>\n"; } - + // Output the text. assert(!P.getString().empty()); Indent(o, indent) << "<key>extended_message</key>\n"; Indent(o, indent); EmitString(o, P.getString()) << '\n'; - + // Output the short text. // FIXME: Really use a short string. Indent(o, indent) << "<key>message</key>\n"; @@ -233,10 +251,10 @@ static void ReportMacro(llvm::raw_ostream& o, const FIDMap& FM, const SourceManager &SM, const LangOptions &LangOpts, unsigned indent) { - + for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end(); I!=E; ++I) { - + switch ((*I)->getKind()) { default: break; @@ -248,16 +266,16 @@ static void ReportMacro(llvm::raw_ostream& o, ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts, indent); break; - } - } + } + } } -static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P, +static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P, const FIDMap& FM, const SourceManager &SM, const LangOptions &LangOpts) { unsigned indent = 4; - + switch (P.getKind()) { case PathDiagnosticPiece::ControlFlow: ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM, @@ -277,38 +295,38 @@ static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P, void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) { if (!D) return; - + if (D->empty()) { delete D; return; } - + // We need to flatten the locations (convert Stmt* to locations) because // the referenced statements may be freed by the time the diagnostics // are emitted. - const_cast<PathDiagnostic*>(D)->flattenLocations(); + const_cast<PathDiagnostic*>(D)->flattenLocations(); BatchedDiags.push_back(D); } -PlistDiagnostics::~PlistDiagnostics() { +PlistDiagnostics::~PlistDiagnostics() { // Build up a set of FIDs that we use by scanning the locations and // ranges of the diagnostics. FIDMap FM; llvm::SmallVector<FileID, 10> Fids; const SourceManager* SM = 0; - - if (!BatchedDiags.empty()) + + if (!BatchedDiags.empty()) SM = &(*BatchedDiags.begin())->begin()->getLocation().getManager(); for (std::vector<const PathDiagnostic*>::iterator DI = BatchedDiags.begin(), DE = BatchedDiags.end(); DI != DE; ++DI) { - + const PathDiagnostic *D = *DI; - + for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I!=E; ++I) { AddFID(FM, Fids, SM, I->getLocation().asLocation()); - + for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(), RE=I->ranges_end(); RI!=RE; ++RI) { AddFID(FM, Fids, SM, RI->getBegin()); @@ -319,71 +337,89 @@ PlistDiagnostics::~PlistDiagnostics() { // Open the file. std::string ErrMsg; - llvm::raw_fd_ostream o(OutputFile.c_str(), false, ErrMsg); + llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg); if (!ErrMsg.empty()) { llvm::errs() << "warning: could not creat file: " << OutputFile << '\n'; return; } - + // Write the plist header. o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " - "http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" "<plist version=\"1.0\">\n"; - + // Write the root object: a <dict> containing... // - "files", an <array> mapping from FIDs to file names - // - "diagnostics", an <array> containing the path diagnostics + // - "diagnostics", an <array> containing the path diagnostics o << "<dict>\n" " <key>files</key>\n" " <array>\n"; - + for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end(); I!=E; ++I) { o << " "; EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n'; } - + o << " </array>\n" " <key>diagnostics</key>\n" " <array>\n"; - + for (std::vector<const PathDiagnostic*>::iterator DI=BatchedDiags.begin(), DE = BatchedDiags.end(); DI!=DE; ++DI) { - + o << " <dict>\n" " <key>path</key>\n"; - + const PathDiagnostic *D = *DI; // Create an owning smart pointer for 'D' just so that we auto-free it // when we exit this method. llvm::OwningPtr<PathDiagnostic> OwnedD(const_cast<PathDiagnostic*>(D)); o << " <array>\n"; - + for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I) ReportDiag(o, *I, FM, *SM, LangOpts); - + o << " </array>\n"; - - // Output the bug type and bug category. + + // Output the bug type and bug category. o << " <key>description</key>"; EmitString(o, D->getDescription()) << '\n'; o << " <key>category</key>"; EmitString(o, D->getCategory()) << '\n'; o << " <key>type</key>"; EmitString(o, D->getBugType()) << '\n'; - + // Output the location of the bug. o << " <key>location</key>\n"; EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2); - + + // Output the diagnostic to the sub-diagnostic client, if any. + if (PF) { + if (!SubPDC.get()) + SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade)); + + FilesMade.clear(); + SubPDC->HandlePathDiagnostic(OwnedD.take()); + SubPDC.reset(0); + + if (!FilesMade.empty()) { + o << " <key>" << PF->getName() << "_files</key>\n"; + o << " <array>\n"; + for (size_t i = 0, n = FilesMade.size(); i < n ; ++i) + o << " <string>" << FilesMade[i] << "</string>\n"; + o << " </array>\n"; + } + } + // Close up the entry. o << " </dict>\n"; } o << " </array>\n"; - + // Finish. o << "</dict>\n</plist>"; } diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index 170ab5e33f5a..25b40c78183c 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -39,7 +39,7 @@ namespace { Out << "<anon>"; } Out << "\n"; - + // Pass up to EmptyActions so that the symbol table is maintained right. return MinimalAction::ActOnDeclarator(S, D); } @@ -69,16 +69,16 @@ namespace { AttributeList *AttrList) { Out << __FUNCTION__ << "\n"; return MinimalAction::ActOnStartClassInterface(AtInterfaceLoc, - ClassName, ClassLoc, + ClassName, ClassLoc, SuperName, SuperLoc, ProtoRefs, NumProtocols, EndProtoLoc, AttrList); } - /// ActOnForwardClassDeclaration - - /// Scope will always be top level file scope. + /// ActOnForwardClassDeclaration - + /// Scope will always be top level file scope. Action::DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc, - IdentifierInfo **IdentList, + IdentifierInfo **IdentList, unsigned NumElts) { Out << __FUNCTION__ << "\n"; return MinimalAction::ActOnForwardClassDeclaration(AtClassLoc, IdentList, @@ -101,15 +101,15 @@ namespace { Out << "\n"; return DeclPtrTy(); } - - /// AddInitializerToDecl - This action is called immediately after - /// ParseDeclarator (when an initializer is present). The code is factored + + /// AddInitializerToDecl - This action is called immediately after + /// ParseDeclarator (when an initializer is present). The code is factored /// this way to make sure we are able to handle the following: /// void func() { int xx = xx; } /// This allows ActOnDeclarator to register "xx" prior to parsing the - /// initializer. The declaration above should still result in a warning, + /// initializer. The declaration above should still result in a warning, /// since the reference to "xx" is uninitialized. - virtual void AddInitializerToDecl(DeclPtrTy Dcl, FullExprArg Init) { + virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) { Out << __FUNCTION__ << "\n"; } @@ -142,7 +142,7 @@ namespace { virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { Out << __FUNCTION__ << "\n"; } - + /// ActOnFunctionDefBody - This is called when a function body has completed /// parsing. Decl is the DeclTy returned by ParseStartOfFunctionDef. virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) { @@ -155,14 +155,14 @@ namespace { Out << __FUNCTION__ << "\n"; return DeclPtrTy(); } - + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { Out << __FUNCTION__ << "\n"; return DeclPtrTy(); } - + /// ActOnLinkageSpec - Parsed a C++ linkage-specification that /// contained braces. Lang/StrSize contains the language string that /// was parsed at location Loc. Decls/NumDecls provides the @@ -170,12 +170,12 @@ namespace { virtual DeclPtrTy ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace, SourceLocation RBrace, const char *Lang, - unsigned StrSize, + unsigned StrSize, DeclPtrTy *Decls, unsigned NumDecls) { Out << __FUNCTION__ << "\n"; return DeclPtrTy(); } - + /// ActOnLinkageSpec - Parsed a C++ linkage-specification without /// braces. Lang/StrSize contains the language string that was /// parsed at location Loc. D is the declaration parsed. @@ -183,42 +183,43 @@ namespace { unsigned StrSize, DeclPtrTy D) { return DeclPtrTy(); } - + //===------------------------------------------------------------------===// // Type Parsing Callbacks. //===------------------------------------------------------------------===// - + virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) { Out << __FUNCTION__ << "\n"; return TypeResult(); } - - virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagType, TagKind TK, + + virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, - bool &Owned) { + MultiTemplateParamsArg TemplateParameterLists, + bool &OwnedDecl, bool &IsDependent) { // TagType is an instance of DeclSpec::TST, indicating what kind of tag this // is (struct/union/enum/class). Out << __FUNCTION__ << "\n"; return DeclPtrTy(); } - + /// Act on @defs() element found when parsing a structure. ClassName is the - /// name of the referenced class. + /// name of the referenced class. virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, IdentifierInfo *ClassName, llvm::SmallVectorImpl<DeclPtrTy> &Decls) { Out << __FUNCTION__ << "\n"; } - virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD, + virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth) { Out << __FUNCTION__ << "\n"; return DeclPtrTy(); } - + virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart, DeclPtrTy IntfDecl, Declarator &D, ExprTy *BitfieldWidth, @@ -226,14 +227,14 @@ namespace { Out << __FUNCTION__ << "\n"; return DeclPtrTy(); } - + virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl, - DeclPtrTy *Fields, unsigned NumFields, + DeclPtrTy *Fields, unsigned NumFields, SourceLocation LBrac, SourceLocation RBrac, AttributeList *AttrList) { Out << __FUNCTION__ << "\n"; } - + virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl, DeclPtrTy LastEnumConstant, SourceLocation IdLoc,IdentifierInfo *Id, @@ -244,7 +245,8 @@ namespace { virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, SourceLocation RBraceLoc, DeclPtrTy EnumDecl, - DeclPtrTy *Elements, unsigned NumElements) { + DeclPtrTy *Elements, unsigned NumElements, + Scope *S, AttributeList *AttrList) { Out << __FUNCTION__ << "\n"; } @@ -270,12 +272,12 @@ namespace { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } - + virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) { Out << __FUNCTION__ << "\n"; return OwningStmtResult(*this, Expr->release()); } - + /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension, /// which can specify an RHS value. virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, @@ -301,7 +303,7 @@ namespace { return StmtEmpty(); } - virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, + virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal) { @@ -327,7 +329,7 @@ namespace { return StmtEmpty(); } virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, - SourceLocation WhileLoc, + SourceLocation WhileLoc, SourceLocation LPLoc, ExprArg Cond, SourceLocation RPLoc){ Out << __FUNCTION__ << "\n"; @@ -372,7 +374,7 @@ namespace { return StmtEmpty(); } virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc, - FullExprArg RetValExp) { + ExprArg RetValExp) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } @@ -488,12 +490,12 @@ namespace { return ExprEmpty(); } - virtual OwningExprResult ActOnCharacterConstant(const Token &) { + virtual OwningExprResult ActOnCharacterConstant(const Token &) { Out << __FUNCTION__ << "\n"; return ExprEmpty(); } - virtual OwningExprResult ActOnNumericConstant(const Token &) { + virtual OwningExprResult ActOnNumericConstant(const Token &) { Out << __FUNCTION__ << "\n"; return ExprEmpty(); } @@ -513,7 +515,7 @@ namespace { } // Postfix Expressions. - virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, + virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Kind, ExprArg Input) { Out << __FUNCTION__ << "\n"; @@ -531,7 +533,8 @@ namespace { tok::TokenKind OpKind, SourceLocation MemberLoc, IdentifierInfo &Member, - DeclPtrTy ImplDecl) { + DeclPtrTy ImplDecl, + const CXXScopeSpec *SS=0) { Out << __FUNCTION__ << "\n"; return ExprEmpty(); } @@ -571,8 +574,9 @@ namespace { Out << __FUNCTION__ << "\n"; return ExprEmpty(); } - virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, - SourceLocation RParenLoc,ExprArg Op){ + virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, + TypeTy *Ty, SourceLocation RParenLoc, + ExprArg Op) { Out << __FUNCTION__ << "\n"; return ExprEmpty(); } @@ -722,8 +726,7 @@ namespace { } virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, - DeclPtrTy Method) - { + DeclPtrTy Method) { Out << __FUNCTION__ << "\n"; } diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index d63d9cbba989..492b31a0ec39 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -32,12 +32,12 @@ using namespace clang; static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, Preprocessor &PP, llvm::raw_ostream &OS) { OS << "#define " << II.getName(); - + if (MI.isFunctionLike()) { OS << '('; if (MI.arg_empty()) ; - else if (MI.getNumArgs() == 1) + else if (MI.getNumArgs() == 1) OS << (*MI.arg_begin())->getName(); else { MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end(); @@ -45,7 +45,7 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, while (AI != E) OS << ',' << (*AI++)->getName(); } - + if (MI.isVariadic()) { if (!MI.arg_empty()) OS << ','; @@ -53,18 +53,18 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, } OS << ')'; } - + // GCC always emits a space, even if the macro body is empty. However, do not // want to emit two spaces if the first token has a leading space. if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace()) OS << ' '; - + llvm::SmallVector<char, 128> SpellingBuffer; for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end(); I != E; ++I) { if (I->hasLeadingSpace()) OS << ' '; - + // Make sure we have enough space in the spelling buffer. if (I->getLength() < SpellingBuffer.size()) SpellingBuffer.resize(I->getLength()); @@ -105,14 +105,14 @@ public: FileType = SrcMgr::C_User; Initialized = false; } - + void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } - + virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType); virtual void Ident(SourceLocation Loc, const std::string &str); - virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, + virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, const std::string &Str); @@ -122,12 +122,12 @@ public: return ConcatInfo.AvoidConcat(PrevTok, Tok); } void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0); - + void HandleNewlinesInToken(const char *TokStr, unsigned Len); - + /// MacroDefined - This hook is called whenever a macro definition is seen. void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI); - + }; } // end anonymous namespace @@ -143,7 +143,7 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, OS << '#' << ' ' << LineNo << ' ' << '"'; OS.write(&CurFilename[0], CurFilename.size()); OS << '"'; - + if (ExtraLen) OS.write(Extra, ExtraLen); @@ -163,12 +163,12 @@ bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { if (DisableLineMarkers) { if (LineNo == CurLine) return false; - + CurLine = LineNo; - + if (!EmittedTokensOnThisLine && !EmittedMacroOnThisLine) return true; - + OS << '\n'; EmittedTokensOnThisLine = false; EmittedMacroOnThisLine = false; @@ -188,9 +188,9 @@ bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) { } } else { WriteLineInfo(LineNo, 0, 0); - } + } - CurLine = LineNo; + CurLine = LineNo; return true; } @@ -210,12 +210,12 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, MoveToLine(IncludeLoc); } else if (Reason == PPCallbacks::SystemHeaderPragma) { MoveToLine(Loc); - + // TODO GCC emits the # directive for this directive on the line AFTER the // directive and emits a bunch of spaces that aren't needed. Emulate this // strange behavior. } - + Loc = SourceMgr.getInstantiationLoc(Loc); // FIXME: Should use presumed line #! CurLine = SourceMgr.getInstantiationLineNumber(Loc); @@ -239,8 +239,8 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, case PPCallbacks::ExitFile: WriteLineInfo(CurLine, " 2", 2); break; - case PPCallbacks::SystemHeaderPragma: - case PPCallbacks::RenameFile: + case PPCallbacks::SystemHeaderPragma: + case PPCallbacks::RenameFile: WriteLineInfo(CurLine); break; } @@ -250,7 +250,7 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, /// void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) { MoveToLine(Loc); - + OS.write("#ident ", strlen("#ident ")); OS.write(&S[0], S.size()); EmittedTokensOnThisLine = true; @@ -263,7 +263,7 @@ void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II, if (!DumpDefines || // Ignore __FILE__ etc. MI->isBuiltinMacro()) return; - + MoveToLine(MI->getDefinitionLoc()); PrintMacroDefinition(*II, *MI, PP, OS); EmittedMacroOnThisLine = true; @@ -271,14 +271,14 @@ void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II, void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, - const IdentifierInfo *Kind, + const IdentifierInfo *Kind, const std::string &Str) { MoveToLine(Loc); OS << "#pragma comment(" << Kind->getName(); - + if (!Str.empty()) { OS << ", \""; - + for (unsigned i = 0, e = Str.size(); i != e; ++i) { unsigned char Char = Str[i]; if (isprint(Char) && Char != '\\' && Char != '"') @@ -291,7 +291,7 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, } OS << '"'; } - + OS << ')'; EmittedTokensOnThisLine = true; } @@ -307,12 +307,12 @@ bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { // newline characters. if (!MoveToLine(Tok.getLocation())) return false; - + // Print out space characters so that the first token on a line is // indented for easy reading. const SourceManager &SourceMgr = PP.getSourceManager(); unsigned ColNo = SourceMgr.getInstantiationColumnNumber(Tok.getLocation()); - + // This hack prevents stuff like: // #define HASH # // HASH define foo bar @@ -321,11 +321,11 @@ bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { // -fpreprocessed mode. if (ColNo <= 1 && Tok.is(tok::hash)) OS << ' '; - + // Otherwise, indent the appropriate number of spaces. for (; ColNo > 1; --ColNo) OS << ' '; - + return true; } @@ -336,18 +336,18 @@ void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr, if (*TokStr != '\n' && *TokStr != '\r') continue; - + ++NumNewlines; - + // If we have \n\r or \r\n, skip both and count as one line. if (Len != 1 && (TokStr[1] == '\n' || TokStr[1] == '\r') && TokStr[0] != TokStr[1]) ++TokStr, --Len; } - + if (NumNewlines == 0) return; - + CurLine += NumNewlines; } @@ -356,7 +356,7 @@ namespace { struct UnknownPragmaHandler : public PragmaHandler { const char *Prefix; PrintPPOutputPPCallbacks *Callbacks; - + UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks) : PragmaHandler(0), Prefix(prefix), Callbacks(callbacks) {} virtual void HandlePragma(Preprocessor &PP, Token &PragmaTok) { @@ -364,7 +364,7 @@ struct UnknownPragmaHandler : public PragmaHandler { // newline characters. Callbacks->MoveToLine(PragmaTok.getLocation()); Callbacks->OS.write(Prefix, strlen(Prefix)); - + // Read and print all of the pragma tokens. while (PragmaTok.isNot(tok::eom)) { if (PragmaTok.hasLeadingSpace()) @@ -385,11 +385,11 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, char Buffer[256]; Token PrevTok; while (1) { - + // If this token is at the start of a line, emit newlines if needed. if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { // done. - } else if (Tok.hasLeadingSpace() || + } else if (Tok.hasLeadingSpace() || // If we haven't emitted a token on this line yet, PrevTok isn't // useful to look at and no concatenation could happen anyway. (Callbacks->hasEmittedTokensOnThisLine() && @@ -397,7 +397,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, Callbacks->AvoidConcat(PrevTok, Tok))) { OS << ' '; } - + if (IdentifierInfo *II = Tok.getIdentifierInfo()) { OS.write(II->getName(), II->getLength()); } else if (Tok.isLiteral() && !Tok.needsCleaning() && @@ -407,24 +407,24 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, const char *TokPtr = Buffer; unsigned Len = PP.getSpelling(Tok, TokPtr); OS.write(TokPtr, Len); - + // Tokens that can contain embedded newlines need to adjust our current - // line number. + // line number. if (Tok.getKind() == tok::comment) Callbacks->HandleNewlinesInToken(TokPtr, Len); } else { std::string S = PP.getSpelling(Tok); OS.write(&S[0], S.size()); - + // Tokens that can contain embedded newlines need to adjust our current - // line number. + // line number. if (Tok.getKind() == tok::comment) Callbacks->HandleNewlinesInToken(&S[0], S.size()); } Callbacks->SetEmittedTokensOnThisLine(); - + if (Tok.is(tok::eof)) break; - + PrevTok = Tok; PP.Lex(Tok); } @@ -456,7 +456,7 @@ void clang::DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) { for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) { MacroInfo &MI = *MacrosByID[i].second; - // Ignore computed macros like __LINE__ and friends. + // Ignore computed macros like __LINE__ and friends. if (MI.isBuiltinMacro()) continue; PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS); diff --git a/lib/Frontend/RewriteBlocks.cpp b/lib/Frontend/RewriteBlocks.cpp index bc855fa87912..25e7fc423849 100644 --- a/lib/Frontend/RewriteBlocks.cpp +++ b/lib/Frontend/RewriteBlocks.cpp @@ -22,7 +22,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallPtrSet.h" -#include <sstream> using namespace clang; using llvm::utostr; @@ -44,28 +43,28 @@ class RewriteBlocks : public ASTConsumer { llvm::SmallVector<BlockExpr *, 32> Blocks; llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs; llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs; - + // Block related declarations. llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls; llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls; llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; - + // The function/method we are rewriting. FunctionDecl *CurFunctionDef; ObjCMethodDecl *CurMethodDef; - + bool IsHeader; - + std::string Preamble; public: - RewriteBlocks(std::string inFile, Diagnostic &D, + RewriteBlocks(std::string inFile, Diagnostic &D, const LangOptions &LOpts); ~RewriteBlocks() { - // Get the buffer corresponding to MainFileID. + // Get the buffer corresponding to MainFileID. // If we haven't changed it, then we are done. - if (const RewriteBuffer *RewriteBuf = + if (const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(MainFileID)) { std::string S(RewriteBuf->begin(), RewriteBuf->end()); printf("%s\n", S.c_str()); @@ -73,7 +72,7 @@ public: printf("No changes\n"); } } - + void Initialize(ASTContext &context); void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen); @@ -87,51 +86,51 @@ public: } void HandleTopLevelSingleDecl(Decl *D); void HandleDeclInMainFile(Decl *D); - - // Top level + + // Top level Stmt *RewriteFunctionBody(Stmt *S); void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); - + // Block specific rewrite rules. std::string SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD=0); - + void RewriteBlockCall(CallExpr *Exp); void RewriteBlockPointerDecl(NamedDecl *VD); void RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD); void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); - - std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, + + std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, const char *funcName, std::string Tag); - std::string SynthesizeBlockFunc(BlockExpr *CE, int i, + std::string SynthesizeBlockFunc(BlockExpr *CE, int i, const char *funcName, std::string Tag); - std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, + std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, bool hasCopyDisposeHelpers); std::string SynthesizeBlockCall(CallExpr *Exp); void SynthesizeBlockLiterals(SourceLocation FunLocStart, const char *FunName); - + void CollectBlockDeclRefInfo(BlockExpr *Exp); void GetBlockCallExprs(Stmt *S); void GetBlockDeclRefExprs(Stmt *S); - + // We avoid calling Type::isBlockPointerType(), since it operates on the // canonical type. We only care if the top-level type is a closure pointer. bool isBlockPointerType(QualType T) { return isa<BlockPointerType>(T); } - + // FIXME: This predicate seems like it would be useful to add to ASTContext. bool isObjCType(QualType T) { if (!LangOpts.ObjC1 && !LangOpts.ObjC2) return false; - + QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); - + if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || OCT == Context->getCanonicalType(Context->getObjCClassType())) return true; - - if (const PointerType *PT = OCT->getAsPointerType()) { - if (isa<ObjCInterfaceType>(PT->getPointeeType()) || + + if (const PointerType *PT = OCT->getAs<PointerType>()) { + if (isa<ObjCInterfaceType>(PT->getPointeeType()) || PT->getPointeeType()->isObjCQualifiedIdType()) return true; } @@ -146,34 +145,34 @@ public: void RewriteFunctionProtoType(QualType funcType, NamedDecl *D); void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); void RewriteCastExpr(CastExpr *CE); - + bool PointerTypeTakesAnyBlockArguments(QualType QT); void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen); }; - + } static bool IsHeaderFile(const std::string &Filename) { std::string::size_type DotPos = Filename.rfind('.'); - + if (DotPos == std::string::npos) { // no file extension - return false; + return false; } - + std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); // C header: .h // C++ header: .hh or .H; return Ext == "h" || Ext == "hh" || Ext == "H"; -} +} RewriteBlocks::RewriteBlocks(std::string inFile, - Diagnostic &D, const LangOptions &LOpts) : + Diagnostic &D, const LangOptions &LOpts) : Diags(D), LangOpts(LOpts) { IsHeader = IsHeaderFile(inFile); CurFunctionDef = 0; CurMethodDef = 0; - RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, + RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, "rewriting failed"); } @@ -186,15 +185,15 @@ ASTConsumer *clang::CreateBlockRewriter(const std::string& InFile, void RewriteBlocks::Initialize(ASTContext &context) { Context = &context; SM = &Context->getSourceManager(); - + // Get the ID and start/end of the main file. MainFileID = SM->getMainFileID(); const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); MainFileStart = MainBuf->getBufferStart(); MainFileEnd = MainBuf->getBufferEnd(); - + Rewrite.setSourceMgr(Context->getSourceManager(), LangOpts); - + if (IsHeader) Preamble = "#pragma once\n"; Preamble += "#ifndef BLOCK_IMPL\n"; @@ -209,7 +208,7 @@ void RewriteBlocks::Initialize(ASTContext &context) { Preamble += " BLOCK_HAS_COPY_DISPOSE = (1<<25),\n"; Preamble += " BLOCK_IS_GLOBAL = (1<<28)\n"; Preamble += "};\n"; - if (LangOpts.Microsoft) + if (LangOpts.Microsoft) Preamble += "#define __OBJC_RW_EXTERN extern \"C\" __declspec(dllimport)\n"; else Preamble += "#define __OBJC_RW_EXTERN extern\n"; @@ -221,14 +220,13 @@ void RewriteBlocks::Initialize(ASTContext &context) { Preamble += "__OBJC_RW_EXTERN void *_NSConcreteGlobalBlock;\n"; Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n"; Preamble += "#endif\n"; - - InsertText(SM->getLocForStartOfFile(MainFileID), + + InsertText(SM->getLocForStartOfFile(MainFileID), Preamble.c_str(), Preamble.size()); } -void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData, - unsigned StrLen) -{ +void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData, + unsigned StrLen) { if (!Rewrite.InsertText(Loc, StrData, StrLen)) return; Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); @@ -236,21 +234,22 @@ void RewriteBlocks::InsertText(SourceLocation Loc, const char *StrData, void RewriteBlocks::ReplaceText(SourceLocation Start, unsigned OrigLength, const char *NewStr, unsigned NewLength) { - if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength)) + if (!Rewrite.ReplaceText(Start, OrigLength, + llvm::StringRef(NewStr, NewLength))) return; Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); } void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) { bool haveBlockPtrs = false; - for (ObjCMethodDecl::param_iterator I = Method->param_begin(), + for (ObjCMethodDecl::param_iterator I = Method->param_begin(), E = Method->param_end(); I != E; ++I) if (isBlockPointerType((*I)->getType())) haveBlockPtrs = true; - + if (!haveBlockPtrs) return; - + // Do a fuzzy rewrite. // We have 1 or more arguments that have closure pointers. SourceLocation Loc = Method->getLocStart(); @@ -260,7 +259,7 @@ void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) { const char *methodPtr = startBuf; std::string Tag = "struct __block_impl *"; - + while (*methodPtr++ && (methodPtr != endBuf)) { switch (*methodPtr) { case ':': @@ -269,13 +268,13 @@ void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) { const char *scanType = ++methodPtr; bool foundBlockPointer = false; unsigned parenCount = 1; - + while (parenCount) { switch (*scanType) { - case '(': - parenCount++; + case '(': + parenCount++; break; - case ')': + case ')': parenCount--; break; case '^': @@ -289,7 +288,7 @@ void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) { Loc = Loc.getFileLocWithOffset(methodPtr-startBuf); assert((Loc.isValid()) && "Invalid Loc"); ReplaceText(Loc, scanType-methodPtr-1, Tag.c_str(), Tag.size()); - + // Advance startBuf. Since the underlying buffer has changed, // it's very important to advance startBuf (so we can correctly // compute a relative Loc the next time around). @@ -305,34 +304,34 @@ void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) { } void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { - for (ObjCInterfaceDecl::instmeth_iterator - I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); + for (ObjCInterfaceDecl::instmeth_iterator + I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); I != E; ++I) RewriteMethodDecl(*I); - for (ObjCInterfaceDecl::classmeth_iterator + for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); I != E; ++I) RewriteMethodDecl(*I); } void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { - for (ObjCCategoryDecl::instmeth_iterator - I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); + for (ObjCCategoryDecl::instmeth_iterator + I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); I != E; ++I) RewriteMethodDecl(*I); - for (ObjCCategoryDecl::classmeth_iterator + for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); I != E; ++I) RewriteMethodDecl(*I); } void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { - for (ObjCProtocolDecl::instmeth_iterator - I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); + for (ObjCProtocolDecl::instmeth_iterator + I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); I != E; ++I) RewriteMethodDecl(*I); - for (ObjCProtocolDecl::classmeth_iterator - I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); + for (ObjCProtocolDecl::classmeth_iterator + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); I != E; ++I) RewriteMethodDecl(*I); } @@ -347,10 +346,10 @@ void RewriteBlocks::HandleTopLevelSingleDecl(Decl *D) { // if we rewrote the #include/#import. SourceLocation Loc = D->getLocation(); Loc = SM->getInstantiationLoc(Loc); - + // If this is for a builtin, ignore it. if (Loc.isInvalid()) return; - + if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) RewriteInterfaceDecl(MD); else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) @@ -374,7 +373,7 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, funcName + "_" + "block_func_" + utostr(i); BlockDecl *BD = CE->getBlockDecl(); - + if (isa<FunctionNoProtoType>(AFT)) { S += "()"; } else if (BD->param_empty()) { @@ -400,19 +399,19 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, S += ')'; } S += " {\n"; - + // 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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); Context->getPointerType((*I)->getType()).getAsStringInternal(Name, Context->PrintingPolicy); 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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); @@ -420,7 +419,7 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i, // // void (^myImportedClosure)(void); // myImportedClosure = ^(void) { setGlobalInt(x + y); }; - // + // // void (^anotherClosure)(void); // anotherClosure = ^(void) { // myImportedClosure(); // import and invoke the closure @@ -445,13 +444,13 @@ std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, std::string Tag) { std::string StructRef = "struct " + Tag; std::string S = "static void __"; - + S += funcName; S += "_block_copy_" + utostr(i); S += "(" + StructRef; S += "*dst, " + StructRef; S += "*src) {"; - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), E = ImportedBlockDecls.end(); I != E; ++I) { S += "_Block_copy_assign(&dst->"; S += (*I)->getNameAsString(); @@ -464,13 +463,13 @@ std::string RewriteBlocks::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, S += "_block_dispose_" + utostr(i); S += "(" + StructRef; S += "*src) {"; - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), E = ImportedBlockDecls.end(); I != E; ++I) { S += "_Block_destroy(src->"; S += (*I)->getNameAsString(); S += ");"; } - S += "}\n"; + S += "}\n"; return S; } @@ -478,20 +477,20 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, bool hasCopyDisposeHelpers) { std::string S = "struct " + Tag; std::string Constructor = " " + Tag; - + S += " {\n struct __block_impl impl;\n"; - + if (hasCopyDisposeHelpers) S += " void *copy;\n void *dispose;\n"; - + Constructor += "(void *fp"; - + if (hasCopyDisposeHelpers) Constructor += ", void *copyHelp, void *disposeHelp"; - + if (BlockDeclRefs.size()) { // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -500,7 +499,7 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, // // void (^myImportedBlock)(void); // myImportedBlock = ^(void) { setGlobalInt(x + y); }; - // + // // void (^anotherBlock)(void); // anotherBlock = ^(void) { // myImportedBlock(); // import and invoke the closure @@ -517,7 +516,7 @@ std::string RewriteBlocks::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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -526,7 +525,7 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, // // void (^myImportedBlock)(void); // myImportedBlock = ^(void) { setGlobalInt(x + y); }; - // + // // void (^anotherBlock)(void); // anotherBlock = ^(void) { // myImportedBlock(); // import and invoke the closure @@ -549,12 +548,12 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, Constructor += ", int flags=0) {\n"; Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof("; Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n"; - + if (hasCopyDisposeHelpers) Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n"; - + // Initialize all "by copy" arguments. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -565,7 +564,7 @@ std::string RewriteBlocks::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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -599,21 +598,21 @@ void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart, CollectBlockDeclRefInfo(Blocks[i]); std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i); - - std::string CI = SynthesizeBlockImpl(Blocks[i], Tag, + + std::string CI = SynthesizeBlockImpl(Blocks[i], Tag, ImportedBlockDecls.size() > 0); InsertText(FunLocStart, CI.c_str(), CI.size()); std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag); - + InsertText(FunLocStart, CF.c_str(), CF.size()); if (ImportedBlockDecls.size()) { std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag); InsertText(FunLocStart, HF.c_str(), HF.size()); } - + BlockDeclRefs.clear(); BlockByRefDecls.clear(); BlockByCopyDecls.clear(); @@ -627,7 +626,7 @@ void RewriteBlocks::SynthesizeBlockLiterals(SourceLocation FunLocStart, void RewriteBlocks::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); const char *FuncName = FD->getNameAsCString(); - + SynthesizeBlockLiterals(FunLocStart, FuncName); } @@ -638,7 +637,7 @@ void RewriteBlocks::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { std::string::size_type loc = 0; while ((loc = FuncName.find(":", loc)) != std::string::npos) FuncName.replace(loc, 1, "_"); - + SynthesizeBlockLiterals(FunLocStart, FuncName.c_str()); } @@ -668,7 +667,7 @@ void RewriteBlocks::GetBlockCallExprs(Stmt *S) { else GetBlockCallExprs(*CI); } - + if (CallExpr *CE = dyn_cast<CallExpr>(S)) { if (CE->getCallee()->getType()->isBlockPointerType()) { BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE; @@ -681,38 +680,38 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) { // Navigate to relevant type information. const char *closureName = 0; const BlockPointerType *CPT = 0; - + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) { closureName = DRE->getDecl()->getNameAsCString(); - CPT = DRE->getType()->getAsBlockPointerType(); + CPT = DRE->getType()->getAs<BlockPointerType>(); } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) { closureName = CDRE->getDecl()->getNameAsCString(); - CPT = CDRE->getType()->getAsBlockPointerType(); + CPT = CDRE->getType()->getAs<BlockPointerType>(); } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) { closureName = MExpr->getMemberDecl()->getNameAsCString(); - CPT = MExpr->getType()->getAsBlockPointerType(); + CPT = MExpr->getType()->getAs<BlockPointerType>(); } else { assert(1 && "RewriteBlockClass: Bad type"); } assert(CPT && "RewriteBlockClass: Bad type"); - const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType(); + const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); assert(FT && "RewriteBlockClass: Bad type"); const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); // FTP will be null for closures that don't take arguments. - + // Build a closure call - start with a paren expr to enforce precedence. std::string BlockCall = "("; - // Synthesize the cast. + // Synthesize the cast. BlockCall += "(" + Exp->getType().getAsString() + "(*)"; BlockCall += "(struct __block_impl *"; if (FTP) { - for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), + for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), E = FTP->arg_type_end(); I && (I != E); ++I) BlockCall += ", " + (*I).getAsString(); } BlockCall += "))"; // close the argument list and paren expression. - + // Invoke the closure. We need to cast it since the declaration type is // bogus (it's a function pointer type) BlockCall += "((struct __block_impl *)"; @@ -722,11 +721,11 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) { PrintingPolicy(LangOpts)); BlockCall += closureExprBuf.str(); BlockCall += ")->FuncPtr)"; - + // Add the arguments. BlockCall += "((struct __block_impl *)"; BlockCall += closureExprBuf.str(); - for (CallExpr::arg_iterator I = Exp->arg_begin(), + for (CallExpr::arg_iterator I = Exp->arg_begin(), E = Exp->arg_end(); I != E; ++I) { std::string syncExprBufS; llvm::raw_string_ostream Buf(syncExprBufS); @@ -738,11 +737,11 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) { void RewriteBlocks::RewriteBlockCall(CallExpr *Exp) { std::string BlockCall = SynthesizeBlockCall(Exp); - + const char *startBuf = SM->getCharacterData(Exp->getLocStart()); const char *endBuf = SM->getCharacterData(Exp->getLocEnd()); - ReplaceText(Exp->getLocStart(), endBuf-startBuf, + ReplaceText(Exp->getLocStart(), endBuf-startBuf, BlockCall.c_str(), BlockCall.size()); } @@ -754,19 +753,19 @@ void RewriteBlocks::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) { void RewriteBlocks::RewriteCastExpr(CastExpr *CE) { SourceLocation LocStart = CE->getLocStart(); SourceLocation LocEnd = CE->getLocEnd(); - + if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) return; - + const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); - + // advance the location to startArgList. const char *argPtr = startBuf; - + while (*argPtr++ && (argPtr < endBuf)) { switch (*argPtr) { - case '^': + case '^': // Replace the '^' with '*'. LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf); ReplaceText(LocStart, 1, "*", 1); @@ -779,31 +778,31 @@ void RewriteBlocks::RewriteCastExpr(CastExpr *CE) { void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { SourceLocation DeclLoc = FD->getLocation(); unsigned parenCount = 0; - + // We have 1 or more arguments that have closure pointers. const char *startBuf = SM->getCharacterData(DeclLoc); const char *startArgList = strchr(startBuf, '('); - + assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); - + parenCount++; // advance the location to startArgList. DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf); assert((DeclLoc.isValid()) && "Invalid DeclLoc"); - + const char *argPtr = startArgList; - + while (*argPtr++ && parenCount) { switch (*argPtr) { - case '^': + case '^': // Replace the '^' with '*'. DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList); ReplaceText(DeclLoc, 1, "*", 1); break; - case '(': - parenCount++; + case '(': + parenCount++; break; - case ')': + case ')': parenCount--; break; } @@ -813,16 +812,16 @@ void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { bool RewriteBlocks::PointerTypeTakesAnyBlockArguments(QualType QT) { const FunctionProtoType *FTP; - const PointerType *PT = QT->getAsPointerType(); + const PointerType *PT = QT->getAs<PointerType>(); if (PT) { - FTP = PT->getPointeeType()->getAsFunctionProtoType(); + FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); } else { - const BlockPointerType *BPT = QT->getAsBlockPointerType(); + const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); - FTP = BPT->getPointeeType()->getAsFunctionProtoType(); + FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); } if (FTP) { - for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), + for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), E = FTP->arg_type_end(); I != E; ++I) if (isBlockPointerType(*I)) return true; @@ -830,15 +829,15 @@ bool RewriteBlocks::PointerTypeTakesAnyBlockArguments(QualType QT) { return false; } -void RewriteBlocks::GetExtentOfArgList(const char *Name, +void RewriteBlocks::GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen) { const char *argPtr = strchr(Name, '('); assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); - + LParen = argPtr; // output the start. argPtr++; // skip past the left paren. unsigned parenCount = 1; - + while (*argPtr && parenCount) { switch (*argPtr) { case '(': parenCount++; break; @@ -855,7 +854,7 @@ void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { RewriteBlockPointerFunctionArgs(FD); return; - } + } // Handle Variables and Typedefs. SourceLocation DeclLoc = ND->getLocation(); QualType DeclT; @@ -865,15 +864,15 @@ void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) { DeclT = TDD->getUnderlyingType(); else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) DeclT = FD->getType(); - else + else assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled"); - + const char *startBuf = SM->getCharacterData(DeclLoc); const char *endBuf = startBuf; // scan backward (from the decl location) for the end of the previous decl. while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) startBuf--; - + // *startBuf != '^' if we are dealing with a pointer to function that // may take block argument types (which will be handled below). if (*startBuf == '^') { @@ -898,7 +897,7 @@ void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) { return; } -void RewriteBlocks::CollectBlockDeclRefInfo(BlockExpr *Exp) { +void RewriteBlocks::CollectBlockDeclRefInfo(BlockExpr *Exp) { // Add initializers for any closure decl refs. GetBlockDeclRefExprs(Exp->getBody()); if (BlockDeclRefs.size()) { @@ -925,7 +924,7 @@ std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) CollectBlockDeclRefInfo(Exp); std::string FuncName; - + if (CurFunctionDef) FuncName = std::string(CurFunctionDef->getNameAsString()); else if (CurMethodDef) { @@ -936,27 +935,27 @@ std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) FuncName.replace(loc, 1, "_"); } else if (VD) FuncName = std::string(VD->getNameAsString()); - + std::string BlockNumber = utostr(Blocks.size()-1); - + std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; - + std::string FunkTypeStr; - + // Get a pointer to the function type so we can cast appropriately. Context->getPointerType(QualType(Exp->getFunctionType(),0)) .getAsStringInternal(FunkTypeStr, Context->PrintingPolicy); - + // Rewrite the closure block with a compound literal. The first cast is // to prevent warnings from the C compiler. std::string Init = "(" + FunkTypeStr; - + Init += ")&" + Tag; - + // Initialize the block function. Init += "((void*)" + Func; - + if (ImportedBlockDecls.size()) { std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber; Init += ",(void*)" + Buf; @@ -966,7 +965,7 @@ std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) // Add initializers for any closure decl refs. if (BlockDeclRefs.size()) { // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { Init += ","; if (isObjCType((*I)->getType())) { @@ -981,7 +980,7 @@ std::string RewriteBlocks::SynthesizeBlockInitExpr(BlockExpr *Exp, VarDecl *VD) } } // Output all "by ref" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { Init += ",&"; Init += (*I)->getNameAsString(); @@ -1007,7 +1006,7 @@ Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) { if (*CI) { if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { RewriteFunctionBody(CBE->getBody()); - + // We've just rewritten the block body in place. // Now we snarf the rewritten text and stash it away for later use. std::string S = Rewrite.getRewritenText(CBE->getSourceRange()); @@ -1030,18 +1029,18 @@ Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) { if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); DI != DE; ++DI) { - + Decl *SD = *DI; if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { if (isBlockPointerType(ND->getType())) RewriteBlockPointerDecl(ND); - else if (ND->getType()->isFunctionPointerType()) + else if (ND->getType()->isFunctionPointerType()) CheckFunctionPointerDecl(ND->getType(), ND); } if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { if (isBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); - else if (TD->getUnderlyingType()->isFunctionPointerType()) + else if (TD->getUnderlyingType()->isFunctionPointerType()) CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); } } @@ -1055,9 +1054,9 @@ Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) { return S; } -void RewriteBlocks::RewriteFunctionProtoType(QualType funcType, NamedDecl *D) { +void RewriteBlocks::RewriteFunctionProtoType(QualType funcType, NamedDecl *D) { if (FunctionProtoType *fproto = dyn_cast<FunctionProtoType>(funcType)) { - for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), + for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), E = fproto->arg_type_end(); I && (I != E); ++I) if (isBlockPointerType(*I)) { // All the args are checked/rewritten. Don't call twice! @@ -1068,7 +1067,7 @@ void RewriteBlocks::RewriteFunctionProtoType(QualType funcType, NamedDecl *D) { } void RewriteBlocks::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { - const PointerType *PT = funcType->getAsPointerType(); + const PointerType *PT = funcType->getAs<PointerType>(); if (PT && PointerTypeTakesAnyBlockArguments(funcType)) RewriteFunctionProtoType(PT->getPointeeType(), ND); } @@ -1090,7 +1089,7 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { // and any copy/dispose helper functions. InsertBlockLiteralsWithinFunction(FD); CurFunctionDef = 0; - } + } return; } if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { @@ -1116,7 +1115,7 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { std::string Init = SynthesizeBlockInitExpr(CBE, VD); // Do the rewrite, using S.size() which contains the rewritten size. ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size()); - SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), + SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getNameAsCString()); } else if (CastExpr *CE = dyn_cast<CastExpr>(VD->getInit())) { RewriteCastExpr(CE); @@ -1135,13 +1134,13 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { if (isBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); - else if (TD->getUnderlyingType()->isFunctionPointerType()) + else if (TD->getUnderlyingType()->isFunctionPointerType()) CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); return; } if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { if (RD->isDefinition()) { - for (RecordDecl::field_iterator i = RD->field_begin(), + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { FieldDecl *FD = *i; if (isBlockPointerType(FD->getType())) diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp index 5ef4892e5bc1..d92f5c78e690 100644 --- a/lib/Frontend/RewriteMacros.cpp +++ b/lib/Frontend/RewriteMacros.cpp @@ -16,10 +16,11 @@ #include "clang/Rewrite/Rewriter.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/SourceManager.h" -#include "llvm/Support/Streams.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" #include "llvm/ADT/OwningPtr.h" +#include <cstdio> + using namespace clang; /// isSameToken - Return true if the two specified tokens start have the same @@ -30,14 +31,14 @@ static bool isSameToken(Token &RawTok, Token &PPTok) { if (PPTok.getKind() == RawTok.getKind() && PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo()) return true; - + // Otherwise, if they are different but have the same identifier info, they // are also considered to be the same. This allows keywords and raw lexed // identifiers with the same name to be treated the same. if (PPTok.getIdentifierInfo() && PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo()) return true; - + return false; } @@ -47,11 +48,11 @@ static bool isSameToken(Token &RawTok, Token &PPTok) { static const Token &GetNextRawTok(const std::vector<Token> &RawTokens, unsigned &CurTok, bool ReturnComment) { assert(CurTok < RawTokens.size() && "Overran eof!"); - + // If the client doesn't want comments and we have one, skip it. if (!ReturnComment && RawTokens[CurTok].is(tok::comment)) ++CurTok; - + return RawTokens[CurTok++]; } @@ -61,24 +62,24 @@ static const Token &GetNextRawTok(const std::vector<Token> &RawTokens, static void LexRawTokensFromMainFile(Preprocessor &PP, std::vector<Token> &RawTokens) { SourceManager &SM = PP.getSourceManager(); - + // Create a lexer to lex all the tokens of the main file in raw mode. Even // though it is in raw mode, it will not return comments. Lexer RawLex(SM.getMainFileID(), SM, PP.getLangOptions()); // Switch on comment lexing because we really do want them. RawLex.SetCommentRetentionState(true); - + Token RawTok; do { RawLex.LexFromRawLexer(RawTok); - + // If we have an identifier with no identifier info for our raw token, look // up the indentifier info. This is important for equality comparison of // identifier tokens. if (RawTok.is(tok::identifier) && !RawTok.getIdentifierInfo()) RawTok.setIdentifierInfo(PP.LookUpIdentifierInfo(RawTok)); - + RawTokens.push_back(RawTok); } while (RawTok.isNot(tok::eof)); } @@ -87,7 +88,7 @@ static void LexRawTokensFromMainFile(Preprocessor &PP, /// RewriteMacrosInInput - Implement -rewrite-macros mode. void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { SourceManager &SM = PP.getSourceManager(); - + Rewriter Rewrite; Rewrite.setSourceMgr(SM, PP.getLangOptions()); RewriteBuffer &RB = Rewrite.getEditBuffer(SM.getMainFileID()); @@ -97,12 +98,12 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { unsigned CurRawTok = 0; Token RawTok = GetNextRawTok(RawTokens, CurRawTok, false); - + // Get the first preprocessing token. PP.EnterMainSourceFile(); Token PPTok; PP.Lex(PPTok); - + // Preprocess the input file in parallel with raw lexing the main file. Ignore // all tokens that are preprocessed from a file other than the main file (e.g. // a header). If we see tokens that are in the preprocessed file but not the @@ -117,7 +118,7 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { PP.Lex(PPTok); continue; } - + // If the raw file hits a preprocessor directive, they will be extra tokens // in the raw file that don't exist in the preprocsesed file. However, we // choose to preserve them in the output file and otherwise handle them @@ -129,16 +130,16 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo(); if (!strcmp(II->getName(), "warning")) { // Comment out #warning. - RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//", 2); + RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//"); } else if (!strcmp(II->getName(), "pragma") && RawTokens[CurRawTok+1].is(tok::identifier) && !strcmp(RawTokens[CurRawTok+1].getIdentifierInfo()->getName(), "mark")){ // Comment out #pragma mark. - RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//", 2); + RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//"); } } - + // Otherwise, if this is a #include or some other directive, just leave it // in the file by skipping over the line. RawTok = GetNextRawTok(RawTokens, CurRawTok, false); @@ -146,7 +147,7 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { RawTok = GetNextRawTok(RawTokens, CurRawTok, false); continue; } - + // Okay, both tokens are from the same file. Get their offsets from the // start of the file. unsigned PPOffs = SM.getFileOffset(PPLoc); @@ -165,7 +166,7 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { // Comment out a whole run of tokens instead of bracketing each one with // comments. Add a leading space if RawTok didn't have one. bool HasSpace = RawTok.hasLeadingSpace(); - RB.InsertTextAfter(RawOffs, " /*"+HasSpace, 2+!HasSpace); + RB.InsertTextAfter(RawOffs, " /*"+HasSpace); unsigned EndPos; do { @@ -173,20 +174,20 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { RawTok = GetNextRawTok(RawTokens, CurRawTok, true); RawOffs = SM.getFileOffset(RawTok.getLocation()); - + if (RawTok.is(tok::comment)) { // Skip past the comment. RawTok = GetNextRawTok(RawTokens, CurRawTok, false); break; } - + } while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine() && (PPOffs != RawOffs || !isSameToken(RawTok, PPTok))); - RB.InsertTextBefore(EndPos, "*/", 2); + RB.InsertTextBefore(EndPos, "*/"); continue; } - + // Otherwise, there was a replacement an expansion. Insert the new token // in the output buffer. Insert the whole run of new tokens at once to get // them in the right order. @@ -199,12 +200,12 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { PPOffs = SM.getFileOffset(PPLoc); } Expansion += ' '; - RB.InsertTextBefore(InsertPos, &Expansion[0], Expansion.size()); + RB.InsertTextBefore(InsertPos, Expansion); } // Get the buffer corresponding to MainFileID. If we haven't changed it, then // we are done. - if (const RewriteBuffer *RewriteBuf = + if (const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(SM.getMainFileID())) { //printf("Changed:\n"); *OS << std::string(RewriteBuf->begin(), RewriteBuf->end()); diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index cf31f2b2deab..55ab78e638bb 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -20,12 +20,11 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Diagnostic.h" #include "clang/Lex/Lexer.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Streams.h" -#include "llvm/Support/raw_ostream.h" using namespace clang; using llvm::utostr; @@ -36,14 +35,14 @@ namespace { const LangOptions &LangOpts; unsigned RewriteFailedDiag; unsigned TryFinallyContainsReturnDiag; - + ASTContext *Context; SourceManager *SM; TranslationUnitDecl *TUDecl; FileID MainFileID; const char *MainFileStart, *MainFileEnd; SourceLocation LastIncLoc; - + llvm::SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; llvm::SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; @@ -54,9 +53,9 @@ namespace { llvm::SmallVector<int, 8> ObjCBcLabelNo; // Remember all the @protocol(<expr>) expressions. llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; - + unsigned NumObjCStringLiterals; - + FunctionDecl *MsgSendFunctionDecl; FunctionDecl *MsgSendSuperFunctionDecl; FunctionDecl *MsgSendStretFunctionDecl; @@ -67,25 +66,25 @@ namespace { FunctionDecl *SelGetUidFunctionDecl; FunctionDecl *CFStringFunctionDecl; FunctionDecl *SuperContructorFunctionDecl; - + // ObjC string constant support. VarDecl *ConstantStringClassReference; RecordDecl *NSStringRecord; - + // ObjC foreach break/continue generation support. int BcLabelCount; - + // Needed for super. ObjCMethodDecl *CurMethodDef; RecordDecl *SuperStructDecl; RecordDecl *ConstantStringDecl; - + TypeDecl *ProtocolTypeDecl; QualType getProtocolType(); - + // Needed for header files being rewritten bool IsHeader; - + std::string InFileName; llvm::raw_ostream* OutFile; @@ -97,7 +96,7 @@ namespace { llvm::SmallVector<BlockExpr *, 32> Blocks; llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs; llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs; - + // Block related declarations. llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls; llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls; @@ -110,7 +109,7 @@ namespace { // This maps a property to it's synthesied message expression. // This allows us to rewrite chained getters (e.g. o.a.b.c). llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters; - + // This maps an original source AST to it's rewritten form. This allows // us to avoid rewriting the same node twice (which is very uncommon). // This is needed to support some of the exotic property rewriting. @@ -118,9 +117,9 @@ namespace { FunctionDecl *CurFunctionDef; VarDecl *GlobalVarDecl; - + bool DisableReplaceStmt; - + static const int OBJC_ABI_VERSION =7 ; public: virtual void Initialize(ASTContext &context); @@ -137,12 +136,12 @@ namespace { bool silenceMacroWarn); ~RewriteObjC() {} - + virtual void HandleTranslationUnit(ASTContext &C); - + void ReplaceStmt(Stmt *Old, Stmt *New) { Stmt *ReplacingStmt = ReplacedNodes[Old]; - + if (ReplacingStmt) return; // We can't rewrite the same node twice. @@ -175,7 +174,7 @@ namespace { const std::string &Str = S.str(); // If replacement succeeded or warning disabled return with no warning. - if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, &Str[0], Str.size())) { + if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { ReplacedNodes[Old] = New; return; } @@ -188,31 +187,33 @@ namespace { void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen, bool InsertAfter = true) { // If insertion succeeded or warning disabled return with no warning. - if (!Rewrite.InsertText(Loc, StrData, StrLen, InsertAfter) || + if (!Rewrite.InsertText(Loc, llvm::StringRef(StrData, StrLen), + InsertAfter) || SilenceRewriteMacroWarning) return; - + Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); } - + void RemoveText(SourceLocation Loc, unsigned StrLen) { // If removal succeeded or warning disabled return with no warning. if (!Rewrite.RemoveText(Loc, StrLen) || SilenceRewriteMacroWarning) return; - + Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); } void ReplaceText(SourceLocation Start, unsigned OrigLength, const char *NewStr, unsigned NewLength) { // If removal succeeded or warning disabled return with no warning. - if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength) || + if (!Rewrite.ReplaceText(Start, OrigLength, + llvm::StringRef(NewStr, NewLength)) || SilenceRewriteMacroWarning) return; - + Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); } - + // Syntactic Rewriting. void RewritePrologue(SourceLocation Loc); void RewriteInclude(); @@ -237,18 +238,18 @@ namespace { QualType getSuperStructType(); QualType getConstantStringStructType(); bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); - + // Expression Rewriting. Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); void CollectPropertySetters(Stmt *S); - + Stmt *CurrentBody; ParentMap *PropParentMap; // created lazily. - + Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart); Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr); - Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, + Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, SourceRange SrcRange); Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); @@ -262,13 +263,13 @@ namespace { Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, SourceLocation OrigEnd); - CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, + CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, Expr **args, unsigned nargs); Stmt *SynthMessageExpr(ObjCMessageExpr *Exp); Stmt *RewriteBreakStmt(BreakStmt *S); Stmt *RewriteContinueStmt(ContinueStmt *S); void SynthCountByEnumWithState(std::string &buf); - + void SynthMsgSendFunctionDecl(); void SynthMsgSendSuperFunctionDecl(); void SynthMsgSendStretFunctionDecl(); @@ -278,14 +279,14 @@ namespace { void SynthGetMetaClassFunctionDecl(); void SynthSelGetUidFunctionDecl(); void SynthSuperContructorFunctionDecl(); - + // Metadata emission. void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, std::string &Result); - + void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, std::string &Result); - + template<typename MethodIterator> void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, MethodIterator MethodEnd, @@ -293,69 +294,69 @@ namespace { const char *prefix, const char *ClassName, std::string &Result); - + void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, const char *prefix, const char *ClassName, std::string &Result); void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, - const char *prefix, + const char *prefix, const char *ClassName, std::string &Result); void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, std::string &Result); - void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, - ObjCIvarDecl *ivar, + void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, + ObjCIvarDecl *ivar, std::string &Result); void RewriteImplementations(); void SynthesizeMetaDataIntoBuffer(std::string &Result); - + // Block rewriting. - void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); + void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); - + void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); - - // Block specific rewrite rules. + + // Block specific rewrite rules. void RewriteBlockCall(CallExpr *Exp); void RewriteBlockPointerDecl(NamedDecl *VD); Stmt *RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD); void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); - - std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, + + std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, const char *funcName, std::string Tag); - std::string SynthesizeBlockFunc(BlockExpr *CE, int i, + std::string SynthesizeBlockFunc(BlockExpr *CE, int i, const char *funcName, std::string Tag); - std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, + std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, bool hasCopyDisposeHelpers); Stmt *SynthesizeBlockCall(CallExpr *Exp); void SynthesizeBlockLiterals(SourceLocation FunLocStart, const char *FunName); - + void CollectBlockDeclRefInfo(BlockExpr *Exp); void GetBlockCallExprs(Stmt *S); void GetBlockDeclRefExprs(Stmt *S); - + // We avoid calling Type::isBlockPointerType(), since it operates on the // canonical type. We only care if the top-level type is a closure pointer. bool isTopLevelBlockPointerType(QualType T) { return isa<BlockPointerType>(T); } - + // FIXME: This predicate seems like it would be useful to add to ASTContext. bool isObjCType(QualType T) { if (!LangOpts.ObjC1 && !LangOpts.ObjC2) return false; - + QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); - + if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || OCT == Context->getCanonicalType(Context->getObjCClassType())) return true; - - if (const PointerType *PT = OCT->getAsPointerType()) { - if (isa<ObjCInterfaceType>(PT->getPointeeType()) || + + if (const PointerType *PT = OCT->getAs<PointerType>()) { + if (isa<ObjCInterfaceType>(PT->getPointeeType()) || PT->getPointeeType()->isObjCQualifiedIdType()) return true; } @@ -365,12 +366,12 @@ namespace { void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen); void RewriteCastExpr(CStyleCastExpr *CE); - + FunctionDecl *SynthBlockInitFunctionDecl(const char *name); Stmt *SynthBlockInitExpr(BlockExpr *Exp); - + void QuoteDoublequotes(std::string &From, std::string &To) { - for(unsigned i = 0; i < From.length(); i++) { + for (unsigned i = 0; i < From.length(); i++) { if (From[i] == '"') To += "\\\""; else @@ -380,10 +381,10 @@ namespace { }; } -void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, - NamedDecl *D) { +void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, + NamedDecl *D) { if (FunctionProtoType *fproto = dyn_cast<FunctionProtoType>(funcType)) { - for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), + for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), E = fproto->arg_type_end(); I && (I != E); ++I) if (isTopLevelBlockPointerType(*I)) { // All the args are checked/rewritten. Don't call twice! @@ -394,24 +395,24 @@ void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, } void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { - const PointerType *PT = funcType->getAsPointerType(); + const PointerType *PT = funcType->getAs<PointerType>(); if (PT && PointerTypeTakesAnyBlockArguments(funcType)) RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); } static bool IsHeaderFile(const std::string &Filename) { std::string::size_type DotPos = Filename.rfind('.'); - + if (DotPos == std::string::npos) { // no file extension - return false; + return false; } - + std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); // C header: .h // C++ header: .hh or .H; return Ext == "h" || Ext == "hh" || Ext == "H"; -} +} RewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS, Diagnostic &D, const LangOptions &LOpts, @@ -419,16 +420,16 @@ RewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS, : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), SilenceRewriteMacroWarning(silenceMacroWarn) { IsHeader = IsHeaderFile(inFile); - RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, + RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, "rewriting sub-expression within a macro (may not be correct)"); - TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning, + TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning, "rewriter doesn't support user-specified control flow semantics " "for @try/@finally (code may not execute properly)"); } ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile, llvm::raw_ostream* OS, - Diagnostic &Diags, + Diagnostic &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning) { return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); @@ -461,15 +462,15 @@ void RewriteObjC::Initialize(ASTContext &context) { PropParentMap = 0; CurrentBody = 0; DisableReplaceStmt = false; - + // Get the ID and start/end of the main file. MainFileID = SM->getMainFileID(); const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); MainFileStart = MainBuf->getBufferStart(); MainFileEnd = MainBuf->getBufferEnd(); - + Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions()); - + // declaring objc_selector outside the parameter list removes a silly // scope related warning... if (IsHeader) @@ -573,7 +574,7 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { // if we rewrote the #include/#import. SourceLocation Loc = D->getLocation(); Loc = SM->getInstantiationLoc(Loc); - + // If this is for a builtin, ignore it. if (Loc.isInvalid()) return; @@ -592,7 +593,7 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { RewriteCategoryDecl(CD); } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { RewriteProtocolDecl(PD); - } else if (ObjCForwardProtocolDecl *FP = + } else if (ObjCForwardProtocolDecl *FP = dyn_cast<ObjCForwardProtocolDecl>(D)){ RewriteForwardProtocolDecl(FP); } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { @@ -618,7 +619,7 @@ void RewriteObjC::RewriteInclude() { 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) { if (*BufPtr == '#') { @@ -629,7 +630,7 @@ void RewriteObjC::RewriteInclude() { return; if (!strncmp(BufPtr, "import", ImportLen)) { // replace import with include - SourceLocation ImportLoc = + SourceLocation ImportLoc = LocStart.getFileLocWithOffset(BufPtr-MainBufStart); ReplaceText(ImportLoc, ImportLen, "include", IncludeLen); BufPtr += ImportLen; @@ -642,27 +643,27 @@ void RewriteObjC::RewriteTabs() { std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); const char *MainBufStart = MainBuf.first; const char *MainBufEnd = MainBuf.second; - + // Loop over the whole file, looking for tabs. for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) { if (*BufPtr != '\t') continue; - + // Okay, we found a tab. This tab will turn into at least one character, // but it depends on which 'virtual column' it is in. Compute that now. unsigned VCol = 0; while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' && BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r') ++VCol; - + // Okay, now that we know the virtual column, we know how many spaces to // insert. We assume 8-character tab-stops. unsigned Spaces = 8-(VCol & 7); - + // Get the location of the tab. SourceLocation TabLoc = SM->getLocForStartOfFile(MainFileID); TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart); - + // Rewrite the single tab character into a sequence of spaces. ReplaceText(TabLoc, 1, " ", Spaces); } @@ -692,35 +693,35 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) return; // FIXME: is this correct? - + // Generate the 'getter' function. ObjCPropertyDecl *PD = PID->getPropertyDecl(); ObjCInterfaceDecl *ClassDecl = PD->getGetterMethodDecl()->getClassInterface(); ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); - + if (!OID) return; - + std::string Getr; RewriteObjCMethodDecl(PD->getGetterMethodDecl(), Getr); Getr += "{ "; // Synthesize an explicit cast to gain access to the ivar. - // FIXME: deal with code generation implications for various property - // attributes (copy, retain, nonatomic). + // FIXME: deal with code generation implications for various property + // attributes (copy, retain, nonatomic). // See objc-act.c:objc_synthesize_new_getter() for details. Getr += "return " + getIvarAccessString(ClassDecl, OID); Getr += "; }"; InsertText(onePastSemiLoc, Getr.c_str(), Getr.size()); if (PD->isReadOnly()) return; - + // Generate the 'setter' function. std::string Setr; RewriteObjCMethodDecl(PD->getSetterMethodDecl(), Setr); Setr += "{ "; // Synthesize an explicit cast to initialize the ivar. - // FIXME: deal with code generation implications for various property - // attributes (copy, retain, nonatomic). + // FIXME: deal with code generation implications for various property + // attributes (copy, retain, nonatomic). // See objc-act.c:objc_synthesize_new_setter() for details. Setr += getIvarAccessString(ClassDecl, OID) + " = "; Setr += PD->getNameAsCString(); @@ -733,7 +734,7 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { SourceLocation startLoc = ClassDecl->getLocation(); const char *startBuf = SM->getCharacterData(startLoc); const char *semiPtr = strchr(startBuf, ';'); - + // Translate to typedef's that forward reference structs with the same name // as the class. As a convenience, we include the original declaration // as a comment. @@ -754,16 +755,16 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { typedefString += ForwardDecl->getNameAsString(); typedefString += ";\n#endif\n"; } - + // Replace the @class with typedefs corresponding to the classes. - ReplaceText(startLoc, semiPtr-startBuf+1, + ReplaceText(startLoc, semiPtr-startBuf+1, typedefString.c_str(), typedefString.size()); } void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { SourceLocation LocStart = Method->getLocStart(); SourceLocation LocEnd = Method->getLocEnd(); - + if (SM->getInstantiationLineNumber(LocEnd) > SM->getInstantiationLineNumber(LocStart)) { InsertText(LocStart, "#if 0\n", 6); @@ -773,26 +774,25 @@ void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { } } -void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) -{ +void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { SourceLocation Loc = prop->getLocation(); - + ReplaceText(Loc, 0, "// ", 3); - + // FIXME: handle properties that are declared across multiple lines. } void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { SourceLocation LocStart = CatDecl->getLocStart(); - + // FIXME: handle category headers that are declared across multiple lines. ReplaceText(LocStart, 0, "// ", 3); - - for (ObjCCategoryDecl::instmeth_iterator - I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); + + for (ObjCCategoryDecl::instmeth_iterator + I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); - for (ObjCCategoryDecl::classmeth_iterator + for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); @@ -803,14 +803,14 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); - + SourceLocation LocStart = PDecl->getLocStart(); - + // FIXME: handle protocol headers that are declared across multiple lines. ReplaceText(LocStart, 0, "// ", 3); - - for (ObjCProtocolDecl::instmeth_iterator - I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); + + for (ObjCProtocolDecl::instmeth_iterator + I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); for (ObjCProtocolDecl::classmeth_iterator @@ -831,14 +831,14 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); ReplaceText(OptionalLoc, strlen("@optional"), CommentedOptional.c_str(), CommentedOptional.size()); - + } 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()); - + } } } @@ -851,7 +851,7 @@ void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) { ReplaceText(LocStart, 0, "// ", 3); } -void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, +void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, std::string &ResultStr) { //fprintf(stderr,"In RewriteObjCMethodDecl\n"); const FunctionType *FPRetType = 0; @@ -864,35 +864,35 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, // syntax (where a decaration models use). QualType retType = OMD->getResultType(); QualType PointeeTy; - if (const PointerType* PT = retType->getAsPointerType()) + if (const PointerType* PT = retType->getAs<PointerType>()) PointeeTy = PT->getPointeeType(); - else if (const BlockPointerType *BPT = retType->getAsBlockPointerType()) + else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) PointeeTy = BPT->getPointeeType(); - if ((FPRetType = PointeeTy->getAsFunctionType())) { + if ((FPRetType = PointeeTy->getAs<FunctionType>())) { ResultStr += FPRetType->getResultType().getAsString(); ResultStr += "(*"; } } else ResultStr += OMD->getResultType().getAsString(); ResultStr += " "; - + // Unique method name std::string NameStr; - + if (OMD->isInstanceMethod()) NameStr += "_I_"; else NameStr += "_C_"; - + NameStr += OMD->getClassInterface()->getNameAsString(); NameStr += "_"; - - if (ObjCCategoryImplDecl *CID = + + if (ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { NameStr += CID->getNameAsString(); NameStr += "_"; } - // Append selector names, replacing ':' with '_' + // Append selector names, replacing ':' with '_' { std::string selString = OMD->getSelector().getAsString(); int len = selString.size(); @@ -904,10 +904,10 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, // Remember this name for metadata emission MethodInternalNames[OMD] = NameStr; ResultStr += NameStr; - + // Rewrite arguments ResultStr += "("; - + // invisible arguments if (OMD->isInstanceMethod()) { QualType selfTy = Context->getObjCInterfaceType(OMD->getClassInterface()); @@ -922,11 +922,11 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, } else ResultStr += Context->getObjCClassType().getAsString(); - + ResultStr += " self, "; ResultStr += Context->getObjCSelType().getAsString(); ResultStr += " _cmd"; - + // Method arguments. for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), E = OMD->param_end(); PI != E; ++PI) { @@ -939,7 +939,7 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, std::string Name = PDecl->getNameAsString(); if (isTopLevelBlockPointerType(PDecl->getType())) { // Make sure we convert "t (^)(...)" to "t (*)(...)". - const BlockPointerType *BPT = PDecl->getType()->getAsBlockPointerType(); + const BlockPointerType *BPT = PDecl->getType()->getAs<BlockPointerType>(); Context->getPointerType(BPT->getPointeeType()).getAsStringInternal(Name, Context->PrintingPolicy); } else @@ -950,10 +950,10 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, if (OMD->isVariadic()) ResultStr += ", ..."; ResultStr += ") "; - + if (FPRetType) { ResultStr += ")"; // close the precedence "scope" for "*". - + // Now, emit the argument types (if any). if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { ResultStr += "("; @@ -975,12 +975,12 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, 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); - + for (ObjCCategoryImplDecl::instmeth_iterator I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); @@ -996,7 +996,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { ReplaceText(LocStart, endBuf-startBuf, ResultStr.c_str(), ResultStr.size()); } - + for (ObjCCategoryImplDecl::classmeth_iterator I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); @@ -1006,15 +1006,15 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { RewriteObjCMethodDecl(OMD, ResultStr); SourceLocation LocStart = OMD->getLocStart(); SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); - + const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); ReplaceText(LocStart, endBuf-startBuf, - ResultStr.c_str(), ResultStr.size()); + ResultStr.c_str(), ResultStr.size()); } for (ObjCCategoryImplDecl::propimpl_iterator I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), - E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); + E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); I != E; ++I) { RewritePropertyImplDecl(*I, IMD, CID); } @@ -1022,7 +1022,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { if (IMD) InsertText(IMD->getLocEnd(), "// ", 3); else - InsertText(CID->getLocEnd(), "// ", 3); + InsertText(CID->getLocEnd(), "// ", 3); } void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { @@ -1042,16 +1042,16 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { ObjCForwardDecls.insert(ClassDecl); } SynthesizeObjCInternalStruct(ClassDecl, ResultStr); - - for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), + + for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), E = ClassDecl->prop_end(); I != E; ++I) RewriteProperty(*I); - for (ObjCInterfaceDecl::instmeth_iterator + for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); - for (ObjCInterfaceDecl::classmeth_iterator - I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); + for (ObjCInterfaceDecl::classmeth_iterator + I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); @@ -1068,20 +1068,20 @@ Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, ObjCPropertyDecl *PDecl = PropRefExpr->getProperty(); llvm::SmallVector<Expr *, 1> ExprVec; ExprVec.push_back(newStmt); - + Stmt *Receiver = PropRefExpr->getBase(); ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver); if (PRE && PropGetters[PRE]) { // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), - PDecl->getSetterName(), PDecl->getType(), - PDecl->getSetterMethodDecl(), - SourceLocation(), SourceLocation(), + MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), + PDecl->getSetterName(), PDecl->getType(), + PDecl->getSetterMethodDecl(), + SourceLocation(), SourceLocation(), &ExprVec[0], 1); Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); - + // Now do the actual rewrite. ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange); //delete BinOp; @@ -1096,18 +1096,18 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { // This allows us to reuse all the fun and games in SynthMessageExpr(). ObjCMessageExpr *MsgExpr; ObjCPropertyDecl *PDecl = PropRefExpr->getProperty(); - + Stmt *Receiver = PropRefExpr->getBase(); - + ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver); if (PRE && PropGetters[PRE]) { // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), - PDecl->getGetterName(), PDecl->getType(), - PDecl->getGetterMethodDecl(), - SourceLocation(), SourceLocation(), + MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), + PDecl->getGetterName(), PDecl->getType(), + PDecl->getGetterMethodDecl(), + SourceLocation(), SourceLocation(), 0, 0); Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); @@ -1126,7 +1126,7 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { return PropRefExpr; // return the original... } else { ReplaceStmt(PropRefExpr, ReplacingStmt); - // delete PropRefExpr; elsewhere... + // delete PropRefExpr; elsewhere... // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references // to things that stay around. Context->Deallocate(MsgExpr); @@ -1134,19 +1134,19 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { } } -Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, +Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart) { ObjCIvarDecl *D = IV->getDecl(); if (CurMethodDef) { - if (const PointerType *pType = IV->getBase()->getType()->getAsPointerType()) { + if (const PointerType *pType = IV->getBase()->getType()->getAs<PointerType>()) { ObjCInterfaceType *iFaceDecl = dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); // lookup which class implements the instance variable. ObjCInterfaceDecl *clsDeclared = 0; - iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), + iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), clsDeclared); assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); - + // Synthesize an explicit cast to gain access to the ivar. std::string RecName = clsDeclared->getIdentifier()->getName(); RecName += "_IMPL"; @@ -1155,14 +1155,16 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation(), II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); - CastExpr *castExpr = new (Context) CStyleCastExpr(castT, IV->getBase(), - castT,SourceLocation(), - SourceLocation()); + CastExpr *castExpr = new (Context) CStyleCastExpr(castT, + CastExpr::CK_Unknown, + IV->getBase(), + castT,SourceLocation(), + SourceLocation()); // Don't forget the parens to enforce the proper binding. ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), IV->getBase()->getLocEnd(), castExpr); - if (IV->isFreeIvar() && + if (IV->isFreeIvar() && CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) { MemberExpr *ME = new (Context) MemberExpr(PE, true, D, IV->getLocation(), @@ -1171,27 +1173,27 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // delete IV; leak for now, see RewritePropertySetter() usage for more info. return ME; } - + ReplaceStmt(IV->getBase(), PE); // 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]. - IV->setBase(PE); + IV->setBase(PE); return IV; } } else { // we are outside a method. assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); - + // Explicit ivar refs need to have a cast inserted. // FIXME: consider sharing some of this code with the code above. - if (const PointerType *pType = IV->getBase()->getType()->getAsPointerType()) { + if (const PointerType *pType = IV->getBase()->getType()->getAs<PointerType>()) { ObjCInterfaceType *iFaceDecl = dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); // lookup which class implements the instance variable. ObjCInterfaceDecl *clsDeclared = 0; - iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), + iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), clsDeclared); assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); - + // Synthesize an explicit cast to gain access to the ivar. std::string RecName = clsDeclared->getIdentifier()->getName(); RecName += "_IMPL"; @@ -1200,7 +1202,9 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation(), II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); - CastExpr *castExpr = new (Context) CStyleCastExpr(castT, IV->getBase(), + CastExpr *castExpr = new (Context) CStyleCastExpr(castT, + CastExpr::CK_Unknown, + IV->getBase(), castT, SourceLocation(), SourceLocation()); // Don't forget the parens to enforce the proper binding. @@ -1210,7 +1214,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // 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]. - IV->setBase(PE); + IV->setBase(PE); return IV; } } @@ -1220,10 +1224,10 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, /// SynthCountByEnumWithState - To print: /// ((unsigned int (*) /// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) -/// (void *)objc_msgSend)((id)l_collection, +/// (void *)objc_msgSend)((id)l_collection, /// sel_registerName( -/// "countByEnumeratingWithState:objects:count:"), -/// &enumState, +/// "countByEnumeratingWithState:objects:count:"), +/// &enumState, /// (id *)items, (unsigned int)16) /// void RewriteObjC::SynthCountByEnumWithState(std::string &buf) { @@ -1245,7 +1249,7 @@ Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { return S; // replace break with goto __break_label std::string buf; - + SourceLocation startLoc = S->getLocStart(); buf = "goto __break_label_"; buf += utostr(ObjCBcLabelNo.back()); @@ -1262,39 +1266,39 @@ Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { return S; // replace continue with goto __continue_label std::string buf; - + SourceLocation startLoc = S->getLocStart(); buf = "goto __continue_label_"; buf += utostr(ObjCBcLabelNo.back()); ReplaceText(startLoc, strlen("continue"), buf.c_str(), buf.size()); - + return 0; } /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. /// It rewrites: /// for ( type elem in collection) { stmts; } - + /// Into: /// { -/// type elem; +/// type elem; /// struct __objcFastEnumerationState enumState = { 0 }; /// id items[16]; /// id l_collection = (id)collection; -/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState +/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState /// objects:items count:16]; /// if (limit) { /// unsigned long startMutations = *enumState.mutationsPtr; /// do { /// unsigned long counter = 0; /// do { -/// if (startMutations != *enumState.mutationsPtr) +/// if (startMutations != *enumState.mutationsPtr) /// objc_enumerationMutation(l_collection); /// elem = (type)enumState.itemsPtr[counter++]; /// stmts; /// __continue_label: ; /// } while (counter < limit); -/// } while (limit = [l_collection countByEnumeratingWithState:&enumState +/// } while (limit = [l_collection countByEnumeratingWithState:&enumState /// objects:items count:16]); /// elem = nil; /// __break_label: ; @@ -1306,11 +1310,11 @@ Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, SourceLocation OrigEnd) { assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); - assert(isa<ObjCForCollectionStmt>(Stmts.back()) && + assert(isa<ObjCForCollectionStmt>(Stmts.back()) && "ObjCForCollectionStmt Statement stack mismatch"); - assert(!ObjCBcLabelNo.empty() && + assert(!ObjCBcLabelNo.empty() && "ObjCForCollectionStmt - Label No stack empty"); - + SourceLocation startLoc = S->getLocStart(); const char *startBuf = SM->getCharacterData(startLoc); const char *elementName; @@ -1331,10 +1335,10 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, else { DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); elementName = DR->getDecl()->getNameAsCString(); - elementTypeAsString + elementTypeAsString = cast<ValueDecl>(DR->getDecl())->getType().getAsString(); } - + // struct __objcFastEnumerationState enumState = { 0 }; buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; // id items[16]; @@ -1353,8 +1357,8 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) startCollectionBuf++; startCollectionBuf += 3; - - // Replace: "for (type element in" with string constructed thus far. + + // Replace: "for (type element in" with string constructed thus far. ReplaceText(startLoc, startCollectionBuf - startBuf, buf.c_str(), buf.size()); // Replace ')' in for '(' type elem in collection ')' with ';' @@ -1362,17 +1366,17 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, const char *rparenBuf = SM->getCharacterData(rightParenLoc); SourceLocation lparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf); buf = ";\n\t"; - + // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState // objects:items count:16]; // which is synthesized into: - // unsigned int limit = + // unsigned int limit = // ((unsigned int (*) // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) - // (void *)objc_msgSend)((id)l_collection, + // (void *)objc_msgSend)((id)l_collection, // sel_registerName( - // "countByEnumeratingWithState:objects:count:"), - // (struct __objcFastEnumerationState *)&state, + // "countByEnumeratingWithState:objects:count:"), + // (struct __objcFastEnumerationState *)&state, // (id *)items, (unsigned int)16); buf += "unsigned long limit =\n\t\t"; SynthCountByEnumWithState(buf); @@ -1382,7 +1386,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, /// do { /// unsigned long counter = 0; /// do { - /// if (startMutations != *enumState.mutationsPtr) + /// if (startMutations != *enumState.mutationsPtr) /// objc_enumerationMutation(l_collection); /// elem = (type)enumState.itemsPtr[counter++]; buf += "if (limit) {\n\t"; @@ -1398,10 +1402,10 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, buf += ")enumState.itemsPtr[counter++];"; // Replace ')' in for '(' type elem in collection ')' with all of these. ReplaceText(lparenLoc, 1, buf.c_str(), buf.size()); - + /// __continue_label: ; /// } while (counter < limit); - /// } while (limit = [l_collection countByEnumeratingWithState:&enumState + /// } while (limit = [l_collection countByEnumeratingWithState:&enumState /// objects:items count:16]); /// elem = nil; /// __break_label: ; @@ -1409,7 +1413,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, /// else /// elem = nil; /// } - /// + /// buf = ";\n\t"; buf += "__continue_label_"; buf += utostr(ObjCBcLabelNo.back()); @@ -1429,7 +1433,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, buf += elementName; buf += " = ((id)0);\n"; buf += "}\n"; - + // Insert all these *after* the statement body. // FIXME: If this should support Obj-C++, support CXXTryStmt if (isa<CompoundStmt>(S->getBody())) { @@ -1454,7 +1458,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, return 0; } -/// RewriteObjCSynchronizedStmt - +/// RewriteObjCSynchronizedStmt - /// This routine rewrites @synchronized(expr) stmt; /// into: /// objc_sync_enter(expr); @@ -1464,16 +1468,16 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { // Get the start location and compute the semi location. SourceLocation startLoc = S->getLocStart(); const char *startBuf = SM->getCharacterData(startLoc); - + assert((*startBuf == '@') && "bogus @synchronized location"); - - std::string buf; + + std::string buf; buf = "objc_sync_enter((id)"; const char *lparenBuf = startBuf; while (*lparenBuf != '(') lparenBuf++; ReplaceText(startLoc, lparenBuf-startBuf+1, buf.c_str(), buf.size()); - // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since - // the sync expression is typically a message expression that's already + // 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). SourceLocation endLoc = S->getSynchBody()->getLocStart(); const char *endBuf = SM->getCharacterData(endLoc); @@ -1490,7 +1494,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { ReplaceText(rparenLoc, 1, buf.c_str(), buf.size()); startLoc = S->getSynchBody()->getLocEnd(); startBuf = SM->getCharacterData(startLoc); - + assert((*startBuf == '}') && "bogus @synchronized block"); SourceLocation lastCurlyLoc = startLoc; buf = "}\nelse {\n"; @@ -1499,8 +1503,9 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf += "{ /* implicit finally clause */\n"; buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; buf += " objc_sync_exit("; - Expr *syncExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(), - S->getSynchExpr(), + Expr *syncExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(), + CastExpr::CK_Unknown, + S->getSynchExpr(), Context->getObjCIdType(), SourceLocation(), SourceLocation()); @@ -1513,21 +1518,21 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; buf += "}\n"; buf += "}"; - + ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); return 0; } -void RewriteObjC::WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S) { +void RewriteObjC::WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S) { // Perform a bottom up traversal of all children. for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E; ++CI) if (*CI) WarnAboutReturnGotoContinueOrBreakStmts(*CI); - if (isa<ReturnStmt>(S) || isa<ContinueStmt>(S) || + if (isa<ReturnStmt>(S) || isa<ContinueStmt>(S) || isa<BreakStmt>(S) || isa<GotoStmt>(S)) { - Diags.Report(Context->getFullLoc(S->getLocStart()), + Diags.Report(Context->getFullLoc(S->getLocStart()), TryFinallyContainsReturnDiag); } return; @@ -1537,7 +1542,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { // Get the start location and compute the semi location. SourceLocation startLoc = S->getLocStart(); const char *startBuf = SM->getCharacterData(startLoc); - + assert((*startBuf == '@') && "bogus @try location"); std::string buf; @@ -1550,12 +1555,12 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; ReplaceText(startLoc, 4, buf.c_str(), buf.size()); - + startLoc = S->getTryBody()->getLocEnd(); startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '}') && "bogus @try block"); - + SourceLocation lastCurlyLoc = startLoc; ObjCAtCatchStmt *catchList = S->getCatchStmts(); if (catchList) { @@ -1566,7 +1571,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += " if (_setjmp(_stack.buf))\n"; buf += " _rethrow = objc_exception_extract(&_stack);\n"; buf += " else { /* @catch continue */"; - + InsertText(startLoc, buf.c_str(), buf.size()); } else { /* no catch list */ buf = "}\nelse {\n"; @@ -1579,15 +1584,15 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { while (catchList) { ParmVarDecl *catchDecl = catchList->getCatchParamDecl(); - if (catchList == S->getCatchStmts()) + if (catchList == S->getCatchStmts()) buf = "if ("; // we are generating code for the first catch clause else buf = "else if ("; startLoc = catchList->getLocStart(); startBuf = SM->getCharacterData(startLoc); - + assert((*startBuf == '@') && "bogus @catch location"); - + const char *lParenLoc = strchr(startBuf, '('); if (catchList->hasEllipsis()) { @@ -1598,19 +1603,18 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { assert(*SM->getCharacterData(catchList->getRParenLoc()) == ')' && "bogus @catch paren location"); assert((*bodyBuf == '{') && "bogus @catch body location"); - + buf += "1) { id _tmp = _caught;"; - Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, - buf.c_str(), buf.size()); + Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf); } else if (catchDecl) { QualType t = catchDecl->getType(); if (t == Context->getObjCIdType()) { buf += "1) { "; ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size()); sawIdTypedCatch = true; - } else if (const PointerType *pType = t->getAsPointerType()) { + } else if (const PointerType *pType = t->getAs<PointerType>()) { ObjCInterfaceType *cls; // Should be a pointer to a class. - + cls = dyn_cast<ObjCInterfaceType>(pType->getPointeeType().getTypePtr()); if (cls) { buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; @@ -1627,9 +1631,9 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { const char *rParenBuf = SM->getCharacterData(rParenLoc); assert((*rParenBuf == ')') && "bogus @catch paren location"); assert((*bodyBuf == '{') && "bogus @catch body location"); - + buf = " = _caught;"; - // Here we replace ") {" with "= _caught;" (which initializes and + // Here we replace ") {" with "= _caught;" (which initializes and // declares the @catch parameter). ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size()); } else { @@ -1643,7 +1647,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { SourceLocation bodyLoc = lastCatchBody->getLocEnd(); assert(*SM->getCharacterData(bodyLoc) == '}' && "bogus @catch body location"); - + // Insert the last (implicit) else clause *before* the right curly brace. bodyLoc = bodyLoc.getFileLocWithOffset(-1); buf = "} /* last catch end */\n"; @@ -1654,7 +1658,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { if (!S->getFinallyStmt()) buf += "}\n"; InsertText(bodyLoc, buf.c_str(), buf.size()); - + // Set lastCurlyLoc lastCurlyLoc = lastCatchBody->getLocEnd(); } @@ -1662,28 +1666,28 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { startLoc = finalStmt->getLocStart(); startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '@') && "bogus @finally start"); - + buf = "/* @finally */"; ReplaceText(startLoc, 8, buf.c_str(), buf.size()); - + Stmt *body = finalStmt->getFinallyBody(); SourceLocation startLoc = body->getLocStart(); SourceLocation endLoc = body->getLocEnd(); assert(*SM->getCharacterData(startLoc) == '{' && "bogus @finally body location"); - assert(*SM->getCharacterData(endLoc) == '}' && + assert(*SM->getCharacterData(endLoc) == '}' && "bogus @finally body location"); - + startLoc = startLoc.getFileLocWithOffset(1); buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; InsertText(startLoc, buf.c_str(), buf.size()); endLoc = endLoc.getFileLocWithOffset(-1); buf = " if (_rethrow) objc_exception_throw(_rethrow);\n"; InsertText(endLoc, buf.c_str(), buf.size()); - + // Set lastCurlyLoc lastCurlyLoc = body->getLocEnd(); - + // Now check for any return/continue/go statements within the @try. WarnAboutReturnGotoContinueOrBreakStmts(S->getTryBody()); } else { /* no finally clause - make sure we synthesize an implicit one */ @@ -1708,14 +1712,14 @@ Stmt *RewriteObjC::RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S) { return 0; } -// This can't be done with ReplaceStmt(S, ThrowExpr), since -// the throw expression is typically a message expression that's already +// This can't be done with ReplaceStmt(S, ThrowExpr), since +// the throw expression is typically a message expression that's already // been rewritten! (which implies the SourceLocation's are invalid). Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { // Get the start location and compute the semi location. SourceLocation startLoc = S->getLocStart(); const char *startBuf = SM->getCharacterData(startLoc); - + assert((*startBuf == '@') && "bogus @throw location"); std::string buf; @@ -1724,12 +1728,12 @@ Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { buf = "objc_exception_throw("; else // add an implicit argument buf = "objc_exception_throw(_caught"; - + // 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()); - + const char *semiBuf = strchr(startBuf, ';'); assert((*semiBuf == ';') && "@throw: can't find ';'"); SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf); @@ -1747,7 +1751,7 @@ Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { StrEncoding.length(), false,StrType, SourceLocation()); ReplaceStmt(Exp, Replacement); - + // Replace this subexpr in the parent. // delete Exp; leak for now, see RewritePropertySetter() usage for more info. return Replacement; @@ -1760,7 +1764,7 @@ Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { // Create a call to sel_registerName("selName"). llvm::SmallVector<Expr*, 8> SelExprs; QualType argType = Context->getPointerType(Context->CharTy); - SelExprs.push_back(StringLiteral::Create(*Context, + SelExprs.push_back(StringLiteral::Create(*Context, Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().size(), false, argType, SourceLocation())); @@ -1775,17 +1779,19 @@ CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( FunctionDecl *FD, Expr **args, unsigned nargs) { // Get the type, we will need to reference it in a couple spots. QualType msgSendType = FD->getType(); - + // Create a reference to the objc_msgSend() declaration. DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, msgSendType, SourceLocation()); - + // Now, we cast the reference to a pointer to the objc_msgSend type. QualType pToFunc = Context->getPointerType(msgSendType); - ImplicitCastExpr *ICE = new (Context) ImplicitCastExpr(pToFunc, DRE, + ImplicitCastExpr *ICE = new (Context) ImplicitCastExpr(pToFunc, + CastExpr::CK_Unknown, + DRE, /*isLvalue=*/false); - - const FunctionType *FT = msgSendType->getAsFunctionType(); - + + const FunctionType *FT = msgSendType->getAs<FunctionType>(); + return new (Context) CallExpr(*Context, ICE, args, nargs, FT->getResultType(), SourceLocation()); } @@ -1820,23 +1826,14 @@ static void scanToNextArgument(const char *&argRef) { } bool RewriteObjC::needToScanForQualifiers(QualType T) { - - if (T->isObjCQualifiedIdType()) - return true; - - if (const PointerType *pType = T->getAsPointerType()) { - Type *pointeeType = pType->getPointeeType().getTypePtr(); - if (isa<ObjCQualifiedInterfaceType>(pointeeType)) - return true; // we have "Class <Protocol> *". - } - return false; + return T->isObjCQualifiedIdType() || T->isObjCQualifiedInterfaceType(); } void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { QualType Type = E->getType(); if (needToScanForQualifiers(Type)) { SourceLocation Loc, EndLoc; - + if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { Loc = ECE->getLParenLoc(); EndLoc = ECE->getRParenLoc(); @@ -1874,7 +1871,7 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { Loc = FD->getLocation(); // Check for ObjC 'id' and class types that have been adorned with protocol // information (id<p>, C<p>*). The protocol references need to be rewritten! - const FunctionType *funcType = FD->getType()->getAsFunctionType(); + const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); assert(funcType && "missing function type"); proto = dyn_cast<FunctionProtoType>(funcType); if (!proto) @@ -1883,10 +1880,10 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { } else return; - + if (needToScanForQualifiers(Type)) { // Since types are unique, we need to scan the buffer. - + const char *endBuf = SM->getCharacterData(Loc); const char *startBuf = endBuf; while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) @@ -1909,16 +1906,16 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { for (unsigned i = 0; i < proto->getNumArgs(); i++) { if (needToScanForQualifiers(proto->getArgType(i))) { // Since types are unique, we need to scan the buffer. - + const char *endBuf = startBuf; // scan forward (from the decl location) for argument types. scanToNextArgument(endBuf); const char *startRef = 0, *endRef = 0; if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { // Get the locations of the startRef, endRef. - SourceLocation LessLoc = + SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startFuncBuf); - SourceLocation GreaterLoc = + SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startFuncBuf+1); // Comment out the protocol references. InsertText(LessLoc, "/*", 2); @@ -1940,14 +1937,13 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { void RewriteObjC::SynthSelGetUidFunctionDecl() { IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); llvm::SmallVector<QualType, 16> ArgTys; - ArgTys.push_back(Context->getPointerType( - Context->CharTy.getQualifiedType(QualType::Const))); + ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/, 0); SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SelGetUidIdent, getFuncType, + SourceLocation(), + SelGetUidIdent, getFuncType, 0, FunctionDecl::Extern, false); } @@ -1975,8 +1971,8 @@ void RewriteObjC::SynthSuperContructorFunctionDecl() { &ArgTys[0], ArgTys.size(), false, 0); SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - msgSendIdent, msgSendType, + SourceLocation(), + msgSendIdent, msgSendType, 0, FunctionDecl::Extern, false); } @@ -1995,7 +1991,7 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { true /*isVariadic*/, 0); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), - msgSendIdent, msgSendType, + msgSendIdent, msgSendType, 0, FunctionDecl::Extern, false); } @@ -2016,8 +2012,8 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/, 0); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - msgSendIdent, msgSendType, + SourceLocation(), + msgSendIdent, msgSendType, 0, FunctionDecl::Extern, false); } @@ -2035,15 +2031,15 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/, 0); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - msgSendIdent, msgSendType, + SourceLocation(), + msgSendIdent, msgSendType, 0, FunctionDecl::Extern, false); } -// SynthMsgSendSuperStretFunctionDecl - +// SynthMsgSendSuperStretFunctionDecl - // id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...); void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { - IdentifierInfo *msgSendIdent = + IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper_stret"); llvm::SmallVector<QualType, 16> ArgTys; RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, @@ -2059,8 +2055,8 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/, 0); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - msgSendIdent, msgSendType, + SourceLocation(), + msgSendIdent, msgSendType, 0, FunctionDecl::Extern, false); } @@ -2078,8 +2074,8 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { &ArgTys[0], ArgTys.size(), true /*isVariadic*/, 0); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - msgSendIdent, msgSendType, + SourceLocation(), + msgSendIdent, msgSendType, 0, FunctionDecl::Extern, false); } @@ -2087,14 +2083,13 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { void RewriteObjC::SynthGetClassFunctionDecl() { IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); llvm::SmallVector<QualType, 16> ArgTys; - ArgTys.push_back(Context->getPointerType( - Context->CharTy.getQualifiedType(QualType::Const))); + ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/, 0); GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - getClassIdent, getClassType, + SourceLocation(), + getClassIdent, getClassType, 0, FunctionDecl::Extern, false); } @@ -2102,14 +2097,13 @@ void RewriteObjC::SynthGetClassFunctionDecl() { void RewriteObjC::SynthGetMetaClassFunctionDecl() { IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); llvm::SmallVector<QualType, 16> ArgTys; - ArgTys.push_back(Context->getPointerType( - Context->CharTy.getQualifiedType(QualType::Const))); + ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), &ArgTys[0], ArgTys.size(), false /*isVariadic*/, 0); GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - getClassIdent, getClassType, + SourceLocation(), + getClassIdent, getClassType, 0, FunctionDecl::Extern, false); } @@ -2142,17 +2136,20 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { Preamble += ","; // The minus 2 removes the begin/end double quotes. Preamble += utostr(prettyBuf.str().size()-2) + "};\n"; - - VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - &Context->Idents.get(S.c_str()), strType, + + VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), + &Context->Idents.get(S.c_str()), strType, 0, VarDecl::Static); DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation()); Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, - Context->getPointerType(DRE->getType()), + Context->getPointerType(DRE->getType()), SourceLocation()); // cast to NSConstantString * - CastExpr *cast = new (Context) CStyleCastExpr(Exp->getType(), Unop, - Exp->getType(), SourceLocation(), SourceLocation()); + CastExpr *cast = new (Context) CStyleCastExpr(Exp->getType(), + CastExpr::CK_Unknown, + Unop, Exp->getType(), + SourceLocation(), + SourceLocation()); ReplaceStmt(Exp, cast); // delete Exp; leak for now, see RewritePropertySetter() usage for more info. return cast; @@ -2161,11 +2158,12 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) { // check if we are sending a message to 'super' if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0; - + if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) { - const PointerType *PT = Super->getType()->getAsPointerType(); - assert(PT); - ObjCInterfaceType *IT = cast<ObjCInterfaceType>(PT->getPointeeType()); + const ObjCObjectPointerType *OPT = + Super->getType()->getAs<ObjCObjectPointerType>(); + assert(OPT); + const ObjCInterfaceType *IT = OPT->getInterfaceType(); return IT->getDecl(); } return 0; @@ -2175,23 +2173,24 @@ ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) { QualType RewriteObjC::getSuperStructType() { if (!SuperStructDecl) { SuperStructDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, - SourceLocation(), + SourceLocation(), &Context->Idents.get("objc_super")); QualType FieldTypes[2]; - + // struct objc_object *receiver; - FieldTypes[0] = Context->getObjCIdType(); + FieldTypes[0] = Context->getObjCIdType(); // struct objc_class *super; - FieldTypes[1] = Context->getObjCClassType(); + FieldTypes[1] = Context->getObjCClassType(); // Create fields for (unsigned i = 0; i < 2; ++i) { - SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, - SourceLocation(), 0, - FieldTypes[i], /*BitWidth=*/0, + SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, + SourceLocation(), 0, + FieldTypes[i], 0, + /*BitWidth=*/0, /*Mutable=*/false)); } - + SuperStructDecl->completeDefinition(*Context); } return Context->getTagDeclType(SuperStructDecl); @@ -2200,25 +2199,25 @@ QualType RewriteObjC::getSuperStructType() { QualType RewriteObjC::getConstantStringStructType() { if (!ConstantStringDecl) { ConstantStringDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, - SourceLocation(), + SourceLocation(), &Context->Idents.get("__NSConstantStringImpl")); QualType FieldTypes[4]; - + // struct objc_object *receiver; - FieldTypes[0] = Context->getObjCIdType(); + FieldTypes[0] = Context->getObjCIdType(); // int flags; - FieldTypes[1] = Context->IntTy; + FieldTypes[1] = Context->IntTy; // char *str; - FieldTypes[2] = Context->getPointerType(Context->CharTy); + FieldTypes[2] = Context->getPointerType(Context->CharTy); // long length; - FieldTypes[3] = Context->LongTy; + FieldTypes[3] = Context->LongTy; // Create fields for (unsigned i = 0; i < 4; ++i) { - ConstantStringDecl->addDecl(FieldDecl::Create(*Context, - ConstantStringDecl, + ConstantStringDecl->addDecl(FieldDecl::Create(*Context, + ConstantStringDecl, SourceLocation(), 0, - FieldTypes[i], + FieldTypes[i], 0, /*BitWidth=*/0, /*Mutable=*/true)); } @@ -2245,7 +2244,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { SynthGetClassFunctionDecl(); if (!GetMetaClassFunctionDecl) SynthGetMetaClassFunctionDecl(); - + // default to objc_msgSend(). FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; // May need to use objc_msgSend_stret() as well. @@ -2257,11 +2256,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { else if (resultType->isRealFloatingType()) MsgSendFlavor = MsgSendFpretFunctionDecl; } - + // Synthesize a call to objc_msgSend(). llvm::SmallVector<Expr*, 8> MsgExprs; IdentifierInfo *clsName = Exp->getClassName(); - + // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend(). if (clsName) { // class message. // FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle @@ -2271,16 +2270,17 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { if (MsgSendStretFlavor) MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); - - ObjCInterfaceDecl *SuperDecl = + + ObjCInterfaceDecl *SuperDecl = CurMethodDef->getClassInterface()->getSuperClass(); llvm::SmallVector<Expr*, 4> InitExprs; - + // set the receiver to self, the first argument to all methods. InitExprs.push_back( - new (Context) CStyleCastExpr(Context->getObjCIdType(), - new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), + new (Context) CStyleCastExpr(Context->getObjCIdType(), + CastExpr::CK_Unknown, + new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), Context->getObjCIdType(), SourceLocation()), Context->getObjCIdType(), @@ -2289,28 +2289,29 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { llvm::SmallVector<Expr*, 8> ClsExprs; QualType argType = Context->getPointerType(Context->CharTy); ClsExprs.push_back(StringLiteral::Create(*Context, - SuperDecl->getIdentifier()->getName(), + SuperDecl->getIdentifier()->getName(), SuperDecl->getIdentifier()->getLength(), false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, - &ClsExprs[0], + &ClsExprs[0], ClsExprs.size()); // To turn off a warning, type-cast to 'id' InitExprs.push_back( // set 'super class', using objc_getClass(). - new (Context) CStyleCastExpr(Context->getObjCIdType(), + new (Context) CStyleCastExpr(Context->getObjCIdType(), + CastExpr::CK_Unknown, Cls, Context->getObjCIdType(), - SourceLocation(), SourceLocation())); + SourceLocation(), SourceLocation())); // struct objc_super QualType superType = getSuperStructType(); Expr *SuperRep; - + if (LangOpts.Microsoft) { SynthSuperContructorFunctionDecl(); // Simulate a contructor call... - DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, + DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, superType, SourceLocation()); SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], - InitExprs.size(), + InitExprs.size(), superType, SourceLocation()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own @@ -2319,21 +2320,22 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) // SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, - Context->getPointerType(SuperRep->getType()), + Context->getPointerType(SuperRep->getType()), SourceLocation()); - SuperRep = new (Context) CStyleCastExpr(Context->getPointerType(superType), - SuperRep, Context->getPointerType(superType), - SourceLocation(), SourceLocation()); - } else { + SuperRep = new (Context) CStyleCastExpr(Context->getPointerType(superType), + CastExpr::CK_Unknown, SuperRep, + Context->getPointerType(superType), + SourceLocation(), SourceLocation()); + } else { // (struct objc_super) { <exprs from above> } - InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(), - &InitExprs[0], InitExprs.size(), + InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(), + &InitExprs[0], InitExprs.size(), SourceLocation()); SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superType, ILE, false); // struct objc_super * SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, - Context->getPointerType(SuperRep->getType()), + Context->getPointerType(SuperRep->getType()), SourceLocation()); } MsgExprs.push_back(SuperRep); @@ -2341,12 +2343,12 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { llvm::SmallVector<Expr*, 8> ClsExprs; QualType argType = Context->getPointerType(Context->CharTy); ClsExprs.push_back(StringLiteral::Create(*Context, - clsName->getName(), + clsName->getName(), clsName->getLength(), false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, - &ClsExprs[0], + &ClsExprs[0], ClsExprs.size()); MsgExprs.push_back(Cls); } @@ -2358,42 +2360,44 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { if (MsgSendStretFlavor) MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); - + llvm::SmallVector<Expr*, 4> InitExprs; - + InitExprs.push_back( - new (Context) CStyleCastExpr(Context->getObjCIdType(), - new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), + new (Context) CStyleCastExpr(Context->getObjCIdType(), + CastExpr::CK_Unknown, + new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), Context->getObjCIdType(), SourceLocation()), Context->getObjCIdType(), SourceLocation(), SourceLocation())); // set the 'receiver'. - + llvm::SmallVector<Expr*, 8> ClsExprs; QualType argType = Context->getPointerType(Context->CharTy); - ClsExprs.push_back(StringLiteral::Create(*Context, - SuperDecl->getIdentifier()->getName(), + ClsExprs.push_back(StringLiteral::Create(*Context, + SuperDecl->getIdentifier()->getName(), SuperDecl->getIdentifier()->getLength(), false, argType, SourceLocation())); CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, - &ClsExprs[0], + &ClsExprs[0], ClsExprs.size()); // To turn off a warning, type-cast to 'id' InitExprs.push_back( // set 'super class', using objc_getClass(). - new (Context) CStyleCastExpr(Context->getObjCIdType(), - Cls, Context->getObjCIdType(), SourceLocation(), SourceLocation())); + new (Context) CStyleCastExpr(Context->getObjCIdType(), + CastExpr::CK_Unknown, + Cls, Context->getObjCIdType(), SourceLocation(), SourceLocation())); // struct objc_super QualType superType = getSuperStructType(); Expr *SuperRep; - + if (LangOpts.Microsoft) { SynthSuperContructorFunctionDecl(); // Simulate a contructor call... - DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, + DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, superType, SourceLocation()); SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], - InitExprs.size(), + InitExprs.size(), superType, SourceLocation()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own @@ -2402,15 +2406,16 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) // SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, - Context->getPointerType(SuperRep->getType()), + Context->getPointerType(SuperRep->getType()), SourceLocation()); - SuperRep = new (Context) CStyleCastExpr(Context->getPointerType(superType), + SuperRep = new (Context) CStyleCastExpr(Context->getPointerType(superType), + CastExpr::CK_Unknown, SuperRep, Context->getPointerType(superType), - SourceLocation(), SourceLocation()); + SourceLocation(), SourceLocation()); } else { // (struct objc_super) { <exprs from above> } - InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(), - &InitExprs[0], InitExprs.size(), + InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(), + &InitExprs[0], InitExprs.size(), SourceLocation()); SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superType, ILE, false); } @@ -2420,8 +2425,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { // Foo<Proto> *. while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) recExpr = CE->getSubExpr(); - recExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(), recExpr, - Context->getObjCIdType(), + recExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(), + CastExpr::CK_Unknown, recExpr, + Context->getObjCIdType(), SourceLocation(), SourceLocation()); MsgExprs.push_back(recExpr); } @@ -2429,14 +2435,14 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { // Create a call to sel_registerName("selName"), it will be the 2nd argument. llvm::SmallVector<Expr*, 8> SelExprs; QualType argType = Context->getPointerType(Context->CharTy); - SelExprs.push_back(StringLiteral::Create(*Context, + SelExprs.push_back(StringLiteral::Create(*Context, Exp->getSelector().getAsString().c_str(), Exp->getSelector().getAsString().size(), false, argType, SourceLocation())); CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, &SelExprs[0], SelExprs.size()); MsgExprs.push_back(SelExp); - + // Now push any user supplied arguments. for (unsigned i = 0; i < Exp->getNumArgs(); i++) { Expr *userExpr = Exp->getArg(i); @@ -2446,18 +2452,21 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { QualType type = ICE->getType()->isObjCQualifiedIdType() ? Context->getObjCIdType() : ICE->getType(); - userExpr = new (Context) CStyleCastExpr(type, userExpr, type, SourceLocation(), SourceLocation()); + userExpr = new (Context) CStyleCastExpr(type, CastExpr::CK_Unknown, + userExpr, type, SourceLocation(), + SourceLocation()); } // Make id<P...> cast into an 'id' cast. else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { if (CE->getType()->isObjCQualifiedIdType()) { while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) userExpr = CE->getSubExpr(); - userExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(), - userExpr, Context->getObjCIdType(), + userExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(), + CastExpr::CK_Unknown, + userExpr, Context->getObjCIdType(), SourceLocation(), SourceLocation()); } - } + } MsgExprs.push_back(userExpr); // We've transferred the ownership to MsgExprs. For now, we *don't* null // out the argument in the original expression (since we aren't deleting @@ -2468,7 +2477,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { CastExpr *cast; llvm::SmallVector<QualType, 8> ArgTypes; QualType returnType; - + // Push 'id' and 'SEL', the 2 implicit arguments. if (MsgSendFlavor == MsgSendSuperFunctionDecl) ArgTypes.push_back(Context->getPointerType(getSuperStructType())); @@ -2480,11 +2489,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), E = OMD->param_end(); PI != E; ++PI) { QualType t = (*PI)->getType()->isObjCQualifiedIdType() - ? Context->getObjCIdType() + ? Context->getObjCIdType() : (*PI)->getType(); // Make sure we convert "t (^)(...)" to "t (*)(...)". if (isTopLevelBlockPointerType(t)) { - const BlockPointerType *BPT = t->getAsBlockPointerType(); + const BlockPointerType *BPT = t->getAs<BlockPointerType>(); t = Context->getPointerType(BPT->getPointeeType()); } ArgTypes.push_back(t); @@ -2496,33 +2505,36 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { } // Get the type, we will need to reference it in a couple spots. QualType msgSendType = MsgSendFlavor->getType(); - + // Create a reference to the objc_msgSend() declaration. - DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, + DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, SourceLocation()); - // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). + // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). // If we don't do this cast, we get the following bizarre warning/note: // xx.m:13: warning: function called through a non-compatible type // xx.m:13: note: if this code is reached, the program will abort - cast = new (Context) CStyleCastExpr(Context->getPointerType(Context->VoidTy), DRE, + cast = new (Context) CStyleCastExpr(Context->getPointerType(Context->VoidTy), + CastExpr::CK_Unknown, DRE, Context->getPointerType(Context->VoidTy), SourceLocation(), SourceLocation()); - + // Now do the "normal" pointer to function cast. - QualType castType = Context->getFunctionType(returnType, + QualType castType = Context->getFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), // If we don't have a method decl, force a variadic cast. Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0); castType = Context->getPointerType(castType); - cast = new (Context) CStyleCastExpr(castType, cast, castType, SourceLocation(), SourceLocation()); + cast = new (Context) CStyleCastExpr(castType, CastExpr::CK_Unknown, cast, + castType, SourceLocation(), + SourceLocation()); // Don't forget the parens to enforce the proper binding. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); - - const FunctionType *FT = msgSendType->getAsFunctionType(); + + const FunctionType *FT = msgSendType->getAs<FunctionType>(); CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], - MsgExprs.size(), + MsgExprs.size(), FT->getResultType(), SourceLocation()); Stmt *ReplacingStmt = CE; if (MsgSendStretFlavor) { @@ -2530,31 +2542,33 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { // call to objc_msgSend_stret and hang both varieties on a conditional // expression which dictate which one to envoke depending on size of // method's return type. - + // Create a reference to the objc_msgSend_stret() declaration. - DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType, + DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType, SourceLocation()); // Need to cast objc_msgSend_stret to "void *" (see above comment). - cast = new (Context) CStyleCastExpr(Context->getPointerType(Context->VoidTy), STDRE, + cast = new (Context) CStyleCastExpr(Context->getPointerType(Context->VoidTy), + CastExpr::CK_Unknown, STDRE, Context->getPointerType(Context->VoidTy), SourceLocation(), SourceLocation()); // Now do the "normal" pointer to function cast. - castType = Context->getFunctionType(returnType, + castType = Context->getFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0); castType = Context->getPointerType(castType); - cast = new (Context) CStyleCastExpr(castType, cast, castType, SourceLocation(), SourceLocation()); - + cast = new (Context) CStyleCastExpr(castType, CastExpr::CK_Unknown, + cast, castType, SourceLocation(), SourceLocation()); + // Don't forget the parens to enforce the proper binding. PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); - - FT = msgSendType->getAsFunctionType(); + + FT = msgSendType->getAs<FunctionType>(); CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], - MsgExprs.size(), + MsgExprs.size(), FT->getResultType(), SourceLocation()); - + // Build sizeof(returnType) - SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true, + SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true, returnType, Context->getSizeType(), SourceLocation(), SourceLocation()); @@ -2562,31 +2576,33 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. // For X86 it is more complicated and some kind of target specific routine // is needed to decide what to do. - unsigned IntSize = + unsigned IntSize = static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); - IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8), + IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8), Context->IntTy, SourceLocation()); - BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit, - BinaryOperator::LE, - Context->IntTy, + BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit, + BinaryOperator::LE, + Context->IntTy, SourceLocation()); // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) - ConditionalOperator *CondExpr = - new (Context) ConditionalOperator(lessThanExpr, CE, STCE, returnType); + ConditionalOperator *CondExpr = + new (Context) ConditionalOperator(lessThanExpr, + SourceLocation(), CE, + SourceLocation(), STCE, returnType); ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr); } - // delete Exp; leak for now, see RewritePropertySetter() usage for more info. + // delete Exp; leak for now, see RewritePropertySetter() usage for more info. return ReplacingStmt; } Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { Stmt *ReplacingStmt = SynthMessageExpr(Exp); - + // Now do the actual rewrite. ReplaceStmt(Exp, ReplacingStmt); - - // delete Exp; leak for now, see RewritePropertySetter() usage for more info. + + // delete Exp; leak for now, see RewritePropertySetter() usage for more info. return ReplacingStmt; } @@ -2594,7 +2610,7 @@ Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { QualType RewriteObjC::getProtocolType() { if (!ProtocolTypeDecl) { ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, - SourceLocation(), + SourceLocation(), &Context->Idents.get("Protocol"), Context->getObjCIdType()); } @@ -2608,23 +2624,24 @@ QualType RewriteObjC::getProtocolType() { Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); IdentifierInfo *ID = &Context->Idents.get(Name); - VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - ID, QualType()/*UNUSED*/, VarDecl::Extern); + VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), + ID, QualType()/*UNUSED*/, 0, VarDecl::Extern); DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation()); Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, Context->getPointerType(DRE->getType()), SourceLocation()); - CastExpr *castExpr = new (Context) CStyleCastExpr(DerefExpr->getType(), DerefExpr, - DerefExpr->getType(), + CastExpr *castExpr = new (Context) CStyleCastExpr(DerefExpr->getType(), + CastExpr::CK_Unknown, + DerefExpr, DerefExpr->getType(), SourceLocation(), SourceLocation()); ReplaceStmt(Exp, castExpr); ProtocolExprDecls.insert(Exp->getProtocol()); - // delete Exp; leak for now, see RewritePropertySetter() usage for more info. + // delete Exp; leak for now, see RewritePropertySetter() usage for more info. return castExpr; - + } -bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, +bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, const char *endBuf) { while (startBuf < endBuf) { if (*startBuf == '#') { @@ -2655,7 +2672,7 @@ bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, std::string &Result) { assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); - assert(CDecl->getNameAsCString() && + assert(CDecl->getNameAsCString() && "Name missing in SynthesizeObjCInternalStruct"); // Do not synthesize more than once. if (ObjCSynthesizedStructs.count(CDecl)) @@ -2664,10 +2681,10 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, int NumIvars = CDecl->ivar_size(); SourceLocation LocStart = CDecl->getLocStart(); SourceLocation LocEnd = CDecl->getLocEnd(); - + const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); - + // If no ivars and no root or if its root, directly or indirectly, // have no ivars (thus not synthesized) then no need to synthesize this class. if ((CDecl->isForwardDecl() || NumIvars == 0) && @@ -2676,8 +2693,8 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size()); return; } - - // FIXME: This has potential of causing problem. If + + // FIXME: This has potential of causing problem. If // SynthesizeObjCInternalStruct is ever called recursively. Result += "\nstruct "; Result += CDecl->getNameAsString(); @@ -2686,7 +2703,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, if (NumIvars > 0) { const char *cursor = strchr(startBuf, '{'); - assert((cursor && endBuf) + assert((cursor && endBuf) && "SynthesizeObjCInternalStruct - malformed @interface"); // If the buffer contains preprocessor directives, we do more fine-grained // rewrites. This is intended to fix code that looks like (which occurs in @@ -2704,7 +2721,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, // // This clause is segregated to avoid breaking the common case. if (BufferContainsPPDirectives(startBuf, cursor)) { - SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : + SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : CDecl->getClassLoc(); const char *endHeader = SM->getCharacterData(L); endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts); @@ -2726,14 +2743,14 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, Result += "_IMPL "; Result += RCDecl->getNameAsString(); Result += "_IVARS;\n"; - + // insert the super class structure definition. SourceLocation OnePastCurly = LocStart.getFileLocWithOffset(cursor-startBuf+1); InsertText(OnePastCurly, Result.c_str(), Result.size()); } cursor++; // past '{' - + // Now comment out any visibility specifiers. while (cursor < endBuf) { if (*cursor == '@') { @@ -2792,7 +2809,7 @@ void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, const char *ClassName, std::string &Result) { if (MethodBegin == MethodEnd) return; - + static bool objc_impl_method = false; if (!objc_impl_method) { /* struct _objc_method { @@ -2806,12 +2823,12 @@ void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, Result += "\tchar *method_types;\n"; Result += "\tvoid *_imp;\n"; Result += "};\n"; - + objc_impl_method = true; } - + // Build _objc_method_list for class's methods if needed - + /* struct { struct _objc_method_list *next_method; int method_count; @@ -2874,13 +2891,13 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, Result += "\tstruct objc_selector *_cmd;\n"; Result += "\tchar *method_types;\n"; Result += "};\n"; - + objc_protocol_methods = true; } // Do not synthesize the protocol more than once. if (ObjCSynthesizedProtocols.count(PDecl)) return; - + if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { unsigned NumMethods = std::distance(PDecl->instmeth_begin(), PDecl->instmeth_end()); @@ -2897,10 +2914,10 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, Result += PDecl->getNameAsString(); Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " "{\n\t" + utostr(NumMethods) + "\n"; - + // Output instance methods declared in this protocol. - for (ObjCProtocolDecl::instmeth_iterator - I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); + for (ObjCProtocolDecl::instmeth_iterator + I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); I != E; ++I) { if (I == PDecl->instmeth_begin()) Result += "\t ,{{(struct objc_selector *)\""; @@ -2915,7 +2932,7 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, } Result += "\t }\n};\n"; } - + // Output class methods declared in this protocol. unsigned NumMethods = std::distance(PDecl->classmeth_begin(), PDecl->classmeth_end()); @@ -2935,9 +2952,9 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, "{\n\t"; Result += utostr(NumMethods); Result += "\n"; - + // Output instance methods declared in this protocol. - for (ObjCProtocolDecl::classmeth_iterator + for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); I != E; ++I) { if (I == PDecl->classmeth_begin()) @@ -2962,7 +2979,7 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, struct _objc_protocol **protocol_list; struct _objc_protocol_method_list *instance_methods; struct _objc_protocol_method_list *class_methods; - }; + }; */ static bool objc_protocol = false; if (!objc_protocol) { @@ -2973,10 +2990,10 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; Result += "};\n"; - + objc_protocol = true; } - + Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; Result += PDecl->getNameAsString(); Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " @@ -2998,7 +3015,7 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, else Result += "0\n"; Result += "};\n"; - + // Mark this protocol as having been generated. if (!ObjCSynthesizedProtocols.insert(PDecl)) assert(false && "protocol already synthesized"); @@ -3010,7 +3027,7 @@ RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, const char *prefix, const char *ClassName, std::string &Result) { if (Protocols.empty()) return; - + for (unsigned i = 0; i != Protocols.size(); i++) RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); @@ -3034,11 +3051,11 @@ RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, "{\n\t0, "; Result += utostr(Protocols.size()); Result += "\n"; - + Result += "\t,{&_OBJC_PROTOCOL_"; Result += Protocols[0]->getNameAsString(); Result += " \n"; - + for (unsigned i = 1; i != Protocols.size(); i++) { Result += "\t ,&_OBJC_PROTOCOL_"; Result += Protocols[i]->getNameAsString(); @@ -3048,24 +3065,24 @@ RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, } -/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category +/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category /// implementation. void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, std::string &Result) { ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); // Find category declaration for this implementation. ObjCCategoryDecl *CDecl; - for (CDecl = ClassDecl->getCategoryList(); CDecl; + for (CDecl = ClassDecl->getCategoryList(); CDecl; CDecl = CDecl->getNextClassCategory()) if (CDecl->getIdentifier() == IDecl->getIdentifier()) break; - + std::string FullCategoryName = ClassDecl->getNameAsString(); FullCategoryName += '_'; FullCategoryName += IDecl->getNameAsString(); - + // Build _objc_method_list for class's instance methods if needed - llvm::SmallVector<ObjCMethodDecl *, 32> + llvm::SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); // If any of our property implementations have associated getters or @@ -3090,12 +3107,12 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), true, "CATEGORY_", FullCategoryName.c_str(), Result); - + // Build _objc_method_list for class's class methods if needed RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), false, "CATEGORY_", FullCategoryName.c_str(), Result); - + // Protocols referenced in class declaration? // Null CDecl is case of a category implementation with no category interface if (CDecl) @@ -3109,11 +3126,11 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, struct _objc_protocol_list *protocols; // Objective-C 1.0 extensions uint32_t size; // sizeof (struct _objc_category) - struct _objc_property_list *instance_properties; // category's own + struct _objc_property_list *instance_properties; // category's own // @property decl. - }; + }; */ - + static bool objc_category = false; if (!objc_category) { Result += "\nstruct _objc_category {\n"; @@ -3122,7 +3139,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, Result += "\tstruct _objc_method_list *instance_methods;\n"; Result += "\tstruct _objc_method_list *class_methods;\n"; Result += "\tstruct _objc_protocol_list *protocols;\n"; - Result += "\tunsigned int size;\n"; + Result += "\tunsigned int size;\n"; Result += "\tstruct _objc_property_list *instance_properties;\n"; Result += "};\n"; objc_category = true; @@ -3134,7 +3151,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, Result += "\"\n\t, \""; Result += ClassDecl->getNameAsString(); Result += "\"\n"; - + if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { Result += "\t, (struct _objc_method_list *)" "&_OBJC_CATEGORY_INSTANCE_METHODS_"; @@ -3151,9 +3168,9 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, } else Result += "\t, 0\n"; - + if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { - Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; + Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; Result += FullCategoryName; Result += "\n"; } @@ -3164,8 +3181,8 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, /// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of /// ivar offset. -void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, - ObjCIvarDecl *ivar, +void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, + ObjCIvarDecl *ivar, std::string &Result) { if (ivar->isBitField()) { // FIXME: The hack below doesn't work for bitfields. For now, we simply @@ -3189,17 +3206,17 @@ void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, std::string &Result) { ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); - + // Explictly declared @interface's are already synthesized. if (CDecl->isImplicitInterfaceDecl()) { - // FIXME: Implementation of a class with no @interface (legacy) doese not + // FIXME: Implementation of a class with no @interface (legacy) doese not // produce correct synthesis as yet. SynthesizeObjCInternalStruct(CDecl, Result); } - + // Build _objc_ivar_list metadata for classes ivars if needed unsigned NumIvars = !IDecl->ivar_empty() - ? IDecl->ivar_size() + ? IDecl->ivar_size() : (CDecl ? CDecl->ivar_size() : 0); if (NumIvars > 0) { static bool objc_ivar = false; @@ -3208,23 +3225,23 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, char *ivar_name; char *ivar_type; int ivar_offset; - }; + }; */ Result += "\nstruct _objc_ivar {\n"; Result += "\tchar *ivar_name;\n"; Result += "\tchar *ivar_type;\n"; Result += "\tint ivar_offset;\n"; Result += "};\n"; - + objc_ivar = true; } /* struct { int ivar_count; struct _objc_ivar ivar_list[nIvars]; - }; + }; */ - Result += "\nstatic struct {\n"; + Result += "\nstatic struct {\n"; Result += "\tint ivar_count;\n"; Result += "\tstruct _objc_ivar ivar_list["; Result += utostr(NumIvars); @@ -3234,11 +3251,11 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, "{\n\t"; Result += utostr(NumIvars); Result += "\n"; - + ObjCInterfaceDecl::ivar_iterator IVI, IVE; llvm::SmallVector<ObjCIvarDecl *, 8> IVars; if (!IDecl->ivar_empty()) { - for (ObjCImplementationDecl::ivar_iterator + for (ObjCImplementationDecl::ivar_iterator IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); IV != IVEnd; ++IV) IVars.push_back(*IV); @@ -3270,12 +3287,12 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, SynthesizeIvarOffsetComputation(IDecl, (*IVI), Result); Result += "}\n"; } - + Result += "\t }\n};\n"; } - + // Build _objc_method_list for class's instance methods if needed - llvm::SmallVector<ObjCMethodDecl *, 32> + llvm::SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); // If any of our property implementations have associated getters or @@ -3299,15 +3316,15 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, } RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), true, "", IDecl->getNameAsCString(), Result); - + // Build _objc_method_list for class's class methods if needed RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), false, "", IDecl->getNameAsCString(), Result); - + // Protocols referenced in class declaration? RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CLASS", CDecl->getNameAsCString(), Result); - + // Declaration of class/meta-class metadata /* struct _objc_class { struct _objc_class *isa; // or const char *root_class_name when metadata @@ -3322,7 +3339,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, struct objc_protocol_list *protocols; const char *ivar_layout; struct _objc_class_ext *ext; - }; + }; */ static bool objc_class = false; if (!objc_class) { @@ -3342,7 +3359,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, Result += "};\n"; objc_class = true; } - + // Meta-class metadata generation. ObjCInterfaceDecl *RootClass = 0; ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); @@ -3351,7 +3368,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, SuperClass = SuperClass->getSuperClass(); } SuperClass = CDecl->getSuperClass(); - + Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; Result += CDecl->getNameAsString(); Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " @@ -3377,7 +3394,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; Result += IDecl->getNameAsString(); - Result += "\n"; + Result += "\n"; } else Result += ", 0\n"; @@ -3389,7 +3406,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, else Result += "\t,0,0,0,0\n"; Result += "};\n"; - + // class metadata generation. Result += "\nstatic struct _objc_class _OBJC_CLASS_"; Result += CDecl->getNameAsString(); @@ -3430,7 +3447,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; Result += CDecl->getNameAsString(); - Result += ", 0\n\t"; + Result += ", 0\n\t"; } else Result += ",0,0"; @@ -3450,25 +3467,25 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, void RewriteObjC::RewriteImplementations() { int ClsDefCount = ClassImplementation.size(); int CatDefCount = CategoryImplementation.size(); - + // Rewrite implemented methods for (int i = 0; i < ClsDefCount; i++) RewriteImplementationDecl(ClassImplementation[i]); - + for (int i = 0; i < CatDefCount; i++) RewriteImplementationDecl(CategoryImplementation[i]); } - + void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { int ClsDefCount = ClassImplementation.size(); int CatDefCount = CategoryImplementation.size(); // This is needed for determining instance variable offsets. - Result += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)\n"; + Result += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)\n"; // For each implemented class, write out all its meta data. for (int i = 0; i < ClsDefCount; i++) RewriteObjCClassMetaData(ClassImplementation[i], Result); - + // For each implemented category, write out all its meta data. for (int i = 0; i < CatDefCount; i++) RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); @@ -3482,9 +3499,9 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { short cls_def_cnt; short cat_def_cnt; void *defs[cls_def_cnt + cat_def_cnt]; - }; + }; */ - + Result += "\nstruct _objc_symtab {\n"; Result += "\tlong sel_ref_cnt;\n"; Result += "\tSEL *refs;\n"; @@ -3492,17 +3509,17 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { Result += "\tshort cat_def_cnt;\n"; Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; Result += "};\n\n"; - + Result += "static struct _objc_symtab " "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; - Result += "\t0, 0, " + utostr(ClsDefCount) + Result += "\t0, 0, " + utostr(ClsDefCount) + ", " + utostr(CatDefCount) + "\n"; for (int i = 0; i < ClsDefCount; i++) { Result += "\t,&_OBJC_CLASS_"; Result += ClassImplementation[i]->getNameAsString(); Result += "\n"; } - + for (int i = 0; i < CatDefCount; i++) { Result += "\t,&_OBJC_CATEGORY_"; Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); @@ -3510,11 +3527,11 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { Result += CategoryImplementation[i]->getNameAsString(); Result += "\n"; } - + Result += "};\n\n"; - + // Write objc_module metadata - + /* struct _objc_module { long version; @@ -3523,7 +3540,7 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { struct _objc_symtab *symtab; } */ - + Result += "\nstruct _objc_module {\n"; Result += "\tlong version;\n"; Result += "\tlong size;\n"; @@ -3532,7 +3549,7 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { Result += "};\n\n"; Result += "static struct _objc_module " "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; - Result += "\t" + utostr(OBJC_ABI_VERSION) + + Result += "\t" + utostr(OBJC_ABI_VERSION) + ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; Result += "};\n\n"; @@ -3540,7 +3557,7 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { if (ProtocolExprDecls.size()) { Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; - for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), + for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), E = ProtocolExprDecls.end(); I != E; ++I) { Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; Result += (*I)->getNameAsString(); @@ -3568,9 +3585,9 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, funcName + "_" + "block_func_" + utostr(i); BlockDecl *BD = CE->getBlockDecl(); - + if (isa<FunctionNoProtoType>(AFT)) { - // No user-supplied arguments. Still need to pass in a pointer to the + // No user-supplied arguments. Still need to pass in a pointer to the // block (to reference imported block decl refs). S += "(" + StructRef + " *__cself)"; } else if (BD->param_empty()) { @@ -3596,19 +3613,19 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, S += ')'; } S += " {\n"; - + // 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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); - Context->getPointerType((*I)->getType()).getAsStringInternal(Name, + Context->getPointerType((*I)->getType()).getAsStringInternal(Name, Context->PrintingPolicy); 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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); @@ -3616,7 +3633,7 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, // // void (^myImportedClosure)(void); // myImportedClosure = ^(void) { setGlobalInt(x + y); }; - // + // // void (^anotherClosure)(void); // anotherClosure = ^(void) { // myImportedClosure(); // import and invoke the closure @@ -3641,13 +3658,13 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, std::string Tag) { std::string StructRef = "struct " + Tag; std::string S = "static void __"; - + S += funcName; S += "_block_copy_" + utostr(i); S += "(" + StructRef; S += "*dst, " + StructRef; S += "*src) {"; - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), E = ImportedBlockDecls.end(); I != E; ++I) { S += "_Block_object_assign((void*)&dst->"; S += (*I)->getNameAsString(); @@ -3660,13 +3677,13 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, S += "_block_dispose_" + utostr(i); S += "(" + StructRef; S += "*src) {"; - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), E = ImportedBlockDecls.end(); I != E; ++I) { S += "_Block_object_dispose((void*)src->"; S += (*I)->getNameAsString(); S += ", 3/*BLOCK_FIELD_IS_OBJECT*/);"; } - S += "}\n"; + S += "}\n"; return S; } @@ -3674,20 +3691,20 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, bool hasCopyDisposeHelpers) { std::string S = "\nstruct " + Tag; std::string Constructor = " " + Tag; - + S += " {\n struct __block_impl impl;\n"; - + if (hasCopyDisposeHelpers) S += " void *copy;\n void *dispose;\n"; - + Constructor += "(void *fp"; - + if (hasCopyDisposeHelpers) Constructor += ", void *copyHelp, void *disposeHelp"; - + if (BlockDeclRefs.size()) { // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -3696,7 +3713,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, // // void (^myImportedBlock)(void); // myImportedBlock = ^(void) { setGlobalInt(x + y); }; - // + // // void (^anotherBlock)(void); // anotherBlock = ^(void) { // myImportedBlock(); // import and invoke the closure @@ -3713,7 +3730,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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -3722,7 +3739,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, // // void (^myImportedBlock)(void); // myImportedBlock = ^(void) { setGlobalInt(x + y); }; - // + // // void (^anotherBlock)(void); // anotherBlock = ^(void) { // myImportedBlock(); // import and invoke the closure @@ -3732,9 +3749,9 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, S += "struct __block_impl *"; Constructor += ", void *" + ArgName; } else { - Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName, + Context->getPointerType((*I)->getType()).getAsStringInternal(FieldName, Context->PrintingPolicy); - Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName, + Context->getPointerType((*I)->getType()).getAsStringInternal(ArgName, Context->PrintingPolicy); Constructor += ", " + ArgName; } @@ -3748,12 +3765,12 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; Constructor += " impl.Size = sizeof("; Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n"; - + if (hasCopyDisposeHelpers) Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n"; - + // Initialize all "by copy" arguments. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -3764,7 +3781,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::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -3801,21 +3818,21 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, CollectBlockDeclRefInfo(Blocks[i]); std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i); - - std::string CI = SynthesizeBlockImpl(Blocks[i], Tag, + + std::string CI = SynthesizeBlockImpl(Blocks[i], Tag, ImportedBlockDecls.size() > 0); InsertText(FunLocStart, CI.c_str(), CI.size()); std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag); - + InsertText(FunLocStart, CF.c_str(), CF.size()); if (ImportedBlockDecls.size()) { std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag); InsertText(FunLocStart, HF.c_str(), HF.size()); } - + BlockDeclRefs.clear(); BlockByRefDecls.clear(); BlockByCopyDecls.clear(); @@ -3829,7 +3846,7 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); const char *FuncName = FD->getNameAsCString(); - + SynthesizeBlockLiterals(FunLocStart, FuncName); } @@ -3843,7 +3860,7 @@ void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { std::string::size_type loc = 0; while ((loc = FuncName.find(":", loc)) != std::string::npos) FuncName.replace(loc, 1, "_"); - + SynthesizeBlockLiterals(FunLocStart, FuncName.c_str()); } @@ -3873,7 +3890,7 @@ void RewriteObjC::GetBlockCallExprs(Stmt *S) { else GetBlockCallExprs(*CI); } - + if (CallExpr *CE = dyn_cast<CallExpr>(S)) { if (CE->getCallee()->getType()->isBlockPointerType()) { BlockCallExprs[dyn_cast<BlockDeclRefExpr>(CE->getCallee())] = CE; @@ -3886,25 +3903,25 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) { // Navigate to relevant type information. const char *closureName = 0; const BlockPointerType *CPT = 0; - + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) { closureName = DRE->getDecl()->getNameAsCString(); - CPT = DRE->getType()->getAsBlockPointerType(); + CPT = DRE->getType()->getAs<BlockPointerType>(); } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) { closureName = CDRE->getDecl()->getNameAsCString(); - CPT = CDRE->getType()->getAsBlockPointerType(); + CPT = CDRE->getType()->getAs<BlockPointerType>(); } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) { closureName = MExpr->getMemberDecl()->getNameAsCString(); - CPT = MExpr->getType()->getAsBlockPointerType(); + CPT = MExpr->getType()->getAs<BlockPointerType>(); } else { assert(1 && "RewriteBlockClass: Bad type"); } assert(CPT && "RewriteBlockClass: Bad type"); - const FunctionType *FT = CPT->getPointeeType()->getAsFunctionType(); + const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); assert(FT && "RewriteBlockClass: Bad type"); const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); // FTP will be null for closures that don't take arguments. - + RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, SourceLocation(), &Context->Idents.get("__block_impl")); @@ -3912,52 +3929,55 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) { // Generate a funky cast. llvm::SmallVector<QualType, 8> ArgTypes; - + // Push the block argument type. ArgTypes.push_back(PtrBlock); if (FTP) { - for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), + for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), E = FTP->arg_type_end(); I && (I != E); ++I) { QualType t = *I; // Make sure we convert "t (^)(...)" to "t (*)(...)". if (isTopLevelBlockPointerType(t)) { - const BlockPointerType *BPT = t->getAsBlockPointerType(); + const BlockPointerType *BPT = t->getAs<BlockPointerType>(); t = Context->getPointerType(BPT->getPointeeType()); } ArgTypes.push_back(t); } } // Now do the pointer to function cast. - QualType PtrToFuncCastType = Context->getFunctionType(Exp->getType(), + QualType PtrToFuncCastType = Context->getFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0); - + PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); - - CastExpr *BlkCast = new (Context) CStyleCastExpr(PtrBlock, Exp->getCallee(), + + CastExpr *BlkCast = new (Context) CStyleCastExpr(PtrBlock, + CastExpr::CK_Unknown, + Exp->getCallee(), PtrBlock, SourceLocation(), SourceLocation()); // Don't forget the parens to enforce the proper binding. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), BlkCast); //PE->dump(); - + FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), - &Context->Idents.get("FuncPtr"), Context->VoidPtrTy, + &Context->Idents.get("FuncPtr"), Context->VoidPtrTy, 0, /*BitWidth=*/0, /*Mutable=*/true); MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), FD->getType()); - - CastExpr *FunkCast = new (Context) CStyleCastExpr(PtrToFuncCastType, ME, + + CastExpr *FunkCast = new (Context) CStyleCastExpr(PtrToFuncCastType, + CastExpr::CK_Unknown, ME, PtrToFuncCastType, SourceLocation(), SourceLocation()); PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); - + llvm::SmallVector<Expr*, 8> BlkExprs; // Add the implicit argument. BlkExprs.push_back(BlkCast); // Add the user arguments. - for (CallExpr::arg_iterator I = Exp->arg_begin(), + for (CallExpr::arg_iterator I = Exp->arg_begin(), E = Exp->arg_end(); I != E; ++I) { BlkExprs.push_back(*I); } @@ -3979,7 +3999,7 @@ void RewriteObjC::RewriteBlockCall(CallExpr *Exp) { // int main() { // __block Foo *f; // __block int i; -// +// // void (^myblock)() = ^() { // [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten). // i = 77; @@ -4006,16 +4026,16 @@ void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { // Need to avoid trying to rewrite casts contained in macros. if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) return; - + const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); - + // advance the location to startArgList. const char *argPtr = startBuf; - + while (*argPtr++ && (argPtr < endBuf)) { switch (*argPtr) { - case '^': + case '^': // Replace the '^' with '*'. LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf); ReplaceText(LocStart, 1, "*", 1); @@ -4028,31 +4048,31 @@ void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { SourceLocation DeclLoc = FD->getLocation(); unsigned parenCount = 0; - + // We have 1 or more arguments that have closure pointers. const char *startBuf = SM->getCharacterData(DeclLoc); const char *startArgList = strchr(startBuf, '('); - + assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); - + parenCount++; // advance the location to startArgList. DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf); assert((DeclLoc.isValid()) && "Invalid DeclLoc"); - + const char *argPtr = startArgList; - + while (*argPtr++ && parenCount) { switch (*argPtr) { - case '^': + case '^': // Replace the '^' with '*'. DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList); ReplaceText(DeclLoc, 1, "*", 1); break; - case '(': - parenCount++; + case '(': + parenCount++; break; - case ')': + case ')': parenCount--; break; } @@ -4062,16 +4082,16 @@ void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { const FunctionProtoType *FTP; - const PointerType *PT = QT->getAsPointerType(); + const PointerType *PT = QT->getAs<PointerType>(); if (PT) { - FTP = PT->getPointeeType()->getAsFunctionProtoType(); + FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); } else { - const BlockPointerType *BPT = QT->getAsBlockPointerType(); + const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); - FTP = BPT->getPointeeType()->getAsFunctionProtoType(); + FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); } if (FTP) { - for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), + for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), E = FTP->arg_type_end(); I != E; ++I) if (isTopLevelBlockPointerType(*I)) return true; @@ -4083,11 +4103,11 @@ void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen) { const char *argPtr = strchr(Name, '('); assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); - + LParen = argPtr; // output the start. argPtr++; // skip past the left paren. unsigned parenCount = 1; - + while (*argPtr && parenCount) { switch (*argPtr) { case '(': parenCount++; break; @@ -4104,7 +4124,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { RewriteBlockPointerFunctionArgs(FD); return; - } + } // Handle Variables and Typedefs. SourceLocation DeclLoc = ND->getLocation(); QualType DeclT; @@ -4114,15 +4134,15 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { DeclT = TDD->getUnderlyingType(); else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) DeclT = FD->getType(); - else + else assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled"); - + const char *startBuf = SM->getCharacterData(DeclLoc); const char *endBuf = startBuf; // scan backward (from the decl location) for the end of the previous decl. while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) startBuf--; - + // *startBuf != '^' if we are dealing with a pointer to function that // may take block argument types (which will be handled below). if (*startBuf == '^') { @@ -4147,7 +4167,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { return; } -void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { +void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { // Add initializers for any closure decl refs. GetBlockDeclRefExprs(Exp->getBody()); if (BlockDeclRefs.size()) { @@ -4172,8 +4192,8 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(const char *name) { IdentifierInfo *ID = &Context->Idents.get(name); QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); - return FunctionDecl::Create(*Context, TUDecl,SourceLocation(), - ID, FType, FunctionDecl::Extern, false, + return FunctionDecl::Create(*Context, TUDecl,SourceLocation(), + ID, FType, 0, FunctionDecl::Extern, false, false); } @@ -4182,7 +4202,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { CollectBlockDeclRefInfo(Exp); std::string FuncName; - + if (CurFunctionDef) FuncName = CurFunctionDef->getNameAsString(); else if (CurMethodDef) { @@ -4193,55 +4213,58 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { FuncName.replace(loc, 1, "_"); } else if (GlobalVarDecl) FuncName = std::string(GlobalVarDecl->getNameAsString()); - + std::string BlockNumber = utostr(Blocks.size()-1); - + std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; - + // Get a pointer to the function type so we can cast appropriately. QualType FType = Context->getPointerType(QualType(Exp->getFunctionType(),0)); FunctionDecl *FD; Expr *NewRep; - + // Simulate a contructor call... FD = SynthBlockInitFunctionDecl(Tag.c_str()); DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, SourceLocation()); - + llvm::SmallVector<Expr*, 4> InitExprs; - + // Initialize the block function. FD = SynthBlockInitFunctionDecl(Func.c_str()); DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); - CastExpr *castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy, Arg, + CastExpr *castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy, + CastExpr::CK_Unknown, Arg, Context->VoidPtrTy, SourceLocation(), SourceLocation()); - InitExprs.push_back(castExpr); - + InitExprs.push_back(castExpr); + if (ImportedBlockDecls.size()) { std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber; FD = SynthBlockInitFunctionDecl(Buf.c_str()); Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); - castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy, Arg, + castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy, + CastExpr::CK_Unknown, Arg, Context->VoidPtrTy, SourceLocation(), SourceLocation()); - InitExprs.push_back(castExpr); - + InitExprs.push_back(castExpr); + Buf = "__" + FuncName + "_block_dispose_" + BlockNumber; FD = SynthBlockInitFunctionDecl(Buf.c_str()); Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); - castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy, Arg, + castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy, + CastExpr::CK_Unknown, Arg, Context->VoidPtrTy, SourceLocation(), SourceLocation()); - InitExprs.push_back(castExpr); + InitExprs.push_back(castExpr); } // Add initializers for any closure decl refs. if (BlockDeclRefs.size()) { Expr *Exp; // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { if (isObjCType((*I)->getType())) { // FIXME: Conform to ABI ([[obj retain] autorelease]). @@ -4250,32 +4273,35 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { } else if (isTopLevelBlockPointerType((*I)->getType())) { FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); - Exp = new (Context) CStyleCastExpr(Context->VoidPtrTy, Arg, - Context->VoidPtrTy, SourceLocation(), + Exp = new (Context) CStyleCastExpr(Context->VoidPtrTy, + CastExpr::CK_Unknown, Arg, + Context->VoidPtrTy, + SourceLocation(), SourceLocation()); } else { FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); } - InitExprs.push_back(Exp); + InitExprs.push_back(Exp); } // Output all "by ref" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, - Context->getPointerType(Exp->getType()), + Context->getPointerType(Exp->getType()), SourceLocation()); - InitExprs.push_back(Exp); + InitExprs.push_back(Exp); } } NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(), FType, SourceLocation()); NewRep = new (Context) UnaryOperator(NewRep, UnaryOperator::AddrOf, - Context->getPointerType(NewRep->getType()), + Context->getPointerType(NewRep->getType()), SourceLocation()); - NewRep = new (Context) CStyleCastExpr(FType, NewRep, FType, SourceLocation(), + NewRep = new (Context) CStyleCastExpr(FType, CastExpr::CK_Unknown, NewRep, + FType, SourceLocation(), SourceLocation()); BlockDeclRefs.clear(); BlockByRefDecls.clear(); @@ -4310,33 +4336,33 @@ void RewriteObjC::CollectPropertySetters(Stmt *S) { } Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { - if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || + if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || isa<DoStmt>(S) || isa<ForStmt>(S)) Stmts.push_back(S); else if (isa<ObjCForCollectionStmt>(S)) { Stmts.push_back(S); ObjCBcLabelNo.push_back(++BcLabelCount); } - + SourceRange OrigStmtRange = S->getSourceRange(); - + // Perform a bottom up rewrite of all children. for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E; ++CI) if (*CI) { Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(*CI); - if (newStmt) + if (newStmt) *CI = newStmt; } - + if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { // Rewrite the block body in place. RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); - + // Now we snarf the rewritten text and stash it away for later use. std::string Str = Rewrite.getRewritenText(BE->getSourceRange()); RewrittenBlockExprs[BE] = Str; - + Stmt *blockTranscribed = SynthBlockInitExpr(BE); //blockTranscribed->dump(); ReplaceStmt(S, blockTranscribed); @@ -4345,7 +4371,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { // Handle specific things. if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) return RewriteAtEncode(AtEncode); - + if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) return RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin()); @@ -4358,7 +4384,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { // Save the source range. Even if we disable the replacement, the // rewritten node will have been inserted into the tree. If the synthesized // node is at the 'end', the rewriter will fail. Consider this: - // self.errorHandler = handler ? handler : + // self.errorHandler = handler ? handler : // ^(NSURL *errorURL, NSError *error) { return (BOOL)1; }; SourceRange SrcRange = BinOp->getSourceRange(); Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS()); @@ -4392,7 +4418,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { // can be used as the setter argument. ReplaceStmt() will still 'see' // the original RHS (since we haven't altered BinOp). // - // This implies the Rewrite* routines can no longer delete the original + // This implies the Rewrite* routines can no longer delete the original // node. As a result, we now leak the original AST nodes. // return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange); @@ -4402,25 +4428,25 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { } if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) return RewriteAtSelector(AtSelector); - + if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) return RewriteObjCStringLiteral(AtString); - + if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { #if 0 // Before we rewrite it, put the original message expression in a comment. SourceLocation startLoc = MessExpr->getLocStart(); SourceLocation endLoc = MessExpr->getLocEnd(); - + const char *startBuf = SM->getCharacterData(startLoc); const char *endBuf = SM->getCharacterData(endLoc); - + std::string messString; messString += "// "; messString.append(startBuf, endBuf-startBuf+1); messString += "\n"; - - // FIXME: Missing definition of + + // FIXME: Missing definition of // InsertText(clang::SourceLocation, char const*, unsigned int). // InsertText(startLoc, messString.c_str(), messString.size()); // Tried this, but it didn't work either... @@ -4428,7 +4454,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { #endif return RewriteMessageExpr(MessExpr); } - + if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) return RewriteObjCTryStmt(StmtTry); @@ -4437,13 +4463,13 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) return RewriteObjCThrowStmt(StmtThrow); - + if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) return RewriteObjCProtocolExpr(ProtocolExp); - - if (ObjCForCollectionStmt *StmtForCollection = + + if (ObjCForCollectionStmt *StmtForCollection = dyn_cast<ObjCForCollectionStmt>(S)) - return RewriteObjCForCollectionStmt(StmtForCollection, + return RewriteObjCForCollectionStmt(StmtForCollection, OrigStmtRange.getEnd()); if (BreakStmt *StmtBreakStmt = dyn_cast<BreakStmt>(S)) @@ -4451,15 +4477,15 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ContinueStmt *StmtContinueStmt = dyn_cast<ContinueStmt>(S)) return RewriteContinueStmt(StmtContinueStmt); - - // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls + + // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls // and cast exprs. if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { // FIXME: What we're doing here is modifying the type-specifier that // precedes the first Decl. In the future the DeclGroup should have - // a separate type-specifier that we can rewrite. + // a separate type-specifier that we can rewrite. RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); - + // Blocks rewrite rules. for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); DI != DE; ++DI) { @@ -4467,26 +4493,26 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { if (isTopLevelBlockPointerType(ND->getType())) RewriteBlockPointerDecl(ND); - else if (ND->getType()->isFunctionPointerType()) + else if (ND->getType()->isFunctionPointerType()) CheckFunctionPointerDecl(ND->getType(), ND); } if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); - else if (TD->getUnderlyingType()->isFunctionPointerType()) + else if (TD->getUnderlyingType()->isFunctionPointerType()) CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); } } } - + if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) RewriteObjCQualifiedInterfaceTypes(CE); - - if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || + + if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || isa<DoStmt>(S) || isa<ForStmt>(S)) { assert(!Stmts.empty() && "Statement stack is empty"); - assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || - isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) + assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || + isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) && "Statement stack mismatch"); Stmts.pop_back(); } @@ -4530,7 +4556,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->isOverloadedOperator()) return; - + // Since function prototypes don't have ParmDecl's, we check the function // prototype. This enables us to rewrite function declarations and // definitions using the same code. @@ -4553,7 +4579,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { // and any copy/dispose helper functions. InsertBlockLiteralsWithinFunction(FD); CurFunctionDef = 0; - } + } return; } if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { @@ -4601,7 +4627,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { delete PropParentMap; PropParentMap = 0; } - SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), + SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getNameAsCString()); GlobalVarDecl = 0; @@ -4615,13 +4641,13 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); - else if (TD->getUnderlyingType()->isFunctionPointerType()) + else if (TD->getUnderlyingType()->isFunctionPointerType()) CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); return; } if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { if (RD->isDefinition()) { - for (RecordDecl::field_iterator i = RD->field_begin(), + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { FieldDecl *FD = *i; if (isTopLevelBlockPointerType(FD->getType())) @@ -4635,29 +4661,29 @@ 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; - + RewriteInclude(); - + // Here's a great place to add any extra declarations that may be needed. // Write out meta data for each @protocol(<expr>). - for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), + for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), E = ProtocolExprDecls.end(); I != E; ++I) RewriteObjCProtocolMetaData(*I, "", "", Preamble); - InsertText(SM->getLocForStartOfFile(MainFileID), + InsertText(SM->getLocForStartOfFile(MainFileID), Preamble.c_str(), Preamble.size(), false); if (ClassImplementation.size() || CategoryImplementation.size()) RewriteImplementations(); // Get the buffer corresponding to MainFileID. If we haven't changed it, then // we are done. - if (const RewriteBuffer *RewriteBuf = + if (const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(MainFileID)) { //printf("Changed:\n"); *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); diff --git a/lib/Frontend/RewriteTest.cpp b/lib/Frontend/RewriteTest.cpp index f9eb58f86740..0414678fb618 100644 --- a/lib/Frontend/RewriteTest.cpp +++ b/lib/Frontend/RewriteTest.cpp @@ -30,8 +30,8 @@ void clang::DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS) { Rewriter.AddTokenBefore(I, "<i>"); Rewriter.AddTokenAfter(I, "</i>"); } - - + + // Print out the output. for (TokenRewriter::token_iterator I = Rewriter.token_begin(), E = Rewriter.token_end(); I != E; ++I) diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index 6ba0a28c7d20..4a3c0bf1c60f 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -32,25 +32,18 @@ namespace { //static const char *getOpcodeStr(BinaryOperator::Opcode Op); - void addSpecialAttribute(const char* pName, StringLiteral* Str) - { + void addSpecialAttribute(const char* pName, StringLiteral* Str) { Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength())); } - void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) - { + void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) { if (S->isArgumentType()) - { Doc.addAttribute(pName, S->getArgumentType()); - } } - void addSpecialAttribute(const char* pName, CXXTypeidExpr* S) - { + void addSpecialAttribute(const char* pName, CXXTypeidExpr* S) { if (S->isTypeOperand()) - { Doc.addAttribute(pName, S->getTypeOperand()); - } } @@ -58,29 +51,21 @@ namespace { StmtXML(DocumentXML& doc) : Doc(doc) { } - + void DumpSubTree(Stmt *S) { - if (S) - { + if (S) { Visit(S); - if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) - { - for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); - DI != DE; ++DI) - { + if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) { + for (DeclStmt::decl_iterator DI = DS->decl_begin(), + DE = DS->decl_end(); DI != DE; ++DI) { Doc.PrintDecl(*DI); } - } - else - { + } else { if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S)) - { Doc.PrintDecl(CCDE->getVarDecl()); - } - for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i) - { + for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); + i != e; ++i) DumpSubTree(*i); - } } Doc.toParent(); } else { @@ -93,12 +78,12 @@ namespace { void Visit##CLASS(CLASS* S) \ { \ typedef CLASS tStmtType; \ - Doc.addSubNode(NAME); + Doc.addSubNode(NAME); -#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN); +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN); #define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN); -#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S); +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN); +#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S); #define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange()); @@ -107,14 +92,14 @@ namespace { const char* pAttributeName = NAME; \ const bool optional = false; \ switch (S->FN) { \ - default: assert(0 && "unknown enum value"); + default: assert(0 && "unknown enum value"); #define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ { \ const char* pAttributeName = NAME; \ const bool optional = true; \ switch (S->FN) { \ - default: assert(0 && "unknown enum value"); + default: assert(0 && "unknown enum value"); #define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; #define END_ENUM_XML } } @@ -133,7 +118,7 @@ namespace { void VisitDeclStmt(DeclStmt *Node); void VisitLabelStmt(LabelStmt *Node); void VisitGotoStmt(GotoStmt *Node); - + // Exprs void VisitExpr(Expr *Node); void VisitDeclRefExpr(DeclRefExpr *Node); @@ -156,14 +141,15 @@ namespace { void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node); void VisitCXXThisExpr(CXXThisExpr *Node); void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node); - + // ObjC void VisitObjCEncodeExpr(ObjCEncodeExpr *Node); void VisitObjCMessageExpr(ObjCMessageExpr* Node); void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); void VisitObjCProtocolExpr(ObjCProtocolExpr *Node); void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node); - void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node); + void VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *Node); void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); void VisitObjCSuperExpr(ObjCSuperExpr *Node); #endif @@ -174,27 +160,22 @@ namespace { // Stmt printing methods. //===----------------------------------------------------------------------===// #if (0) -void StmtXML::VisitStmt(Stmt *Node) -{ +void StmtXML::VisitStmt(Stmt *Node) { // nothing special to do } -void StmtXML::VisitDeclStmt(DeclStmt *Node) -{ +void StmtXML::VisitDeclStmt(DeclStmt *Node) { for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end(); - DI != DE; ++DI) - { + DI != DE; ++DI) { Doc.PrintDecl(*DI); } } -void StmtXML::VisitLabelStmt(LabelStmt *Node) -{ +void StmtXML::VisitLabelStmt(LabelStmt *Node) { Doc.addAttribute("name", Node->getName()); } -void StmtXML::VisitGotoStmt(GotoStmt *Node) -{ +void StmtXML::VisitGotoStmt(GotoStmt *Node) { Doc.addAttribute("name", Node->getLabel()->getName()); } @@ -335,9 +316,7 @@ void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof"); Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0"); if (Node->isArgumentType()) - { DumpTypeExpr(Node->getArgumentType()); - } } void StmtXML::VisitMemberExpr(MemberExpr *Node) { @@ -414,7 +393,7 @@ void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) { DumpExpr(Node); Doc.addAttribute("selector", Node->getSelector().getAsString()); IdentifierInfo* clsName = Node->getClassName(); - if (clsName) + if (clsName) Doc.addAttribute("class", clsName->getName()); } @@ -438,7 +417,8 @@ void StmtXML::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) { Doc.addAttribute("property", Node->getProperty()->getNameAsString()); } -void StmtXML::VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node) { +void StmtXML::VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *Node) { DumpExpr(Node); ObjCMethodDecl *Getter = Node->getGetterMethod(); ObjCMethodDecl *Setter = Node->getSetterMethod(); diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp index a4518ee7e689..34bc3c796aa8 100644 --- a/lib/Frontend/TextDiagnosticBuffer.cpp +++ b/lib/Frontend/TextDiagnosticBuffer.cpp @@ -17,7 +17,7 @@ using namespace clang; /// HandleDiagnostic - Store the errors, warnings, and notes that are /// reported. -/// +/// void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info) { llvm::SmallString<100> StrC; diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index d4c7e0f6f330..63d9a50b368b 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -66,7 +66,7 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, SourceLocation Begin = SM.getInstantiationLoc(R.getBegin()); SourceLocation End = SM.getInstantiationLoc(R.getEnd()); - + // If the End location and the start location are the same and are a macro // location, then the range was something that came from a macro expansion // or _Pragma. If this is an object-like macro, the best we can do is to @@ -74,15 +74,15 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, // highlight the arguments. if (Begin == End && R.getEnd().isMacroID()) End = SM.getInstantiationRange(R.getEnd()).second; - + unsigned StartLineNo = SM.getInstantiationLineNumber(Begin); if (StartLineNo > LineNo || SM.getFileID(Begin) != FID) return; // No intersection. - + unsigned EndLineNo = SM.getInstantiationLineNumber(End); if (EndLineNo < LineNo || SM.getFileID(End) != FID) return; // No intersection. - + // Compute the column number of the start. unsigned StartColNo = 0; if (StartLineNo == LineNo) { @@ -94,21 +94,21 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, while (StartColNo < SourceLine.size() && (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t')) ++StartColNo; - + // Compute the column number of the end. unsigned EndColNo = CaretLine.size(); if (EndLineNo == LineNo) { EndColNo = SM.getInstantiationColumnNumber(End); if (EndColNo) { --EndColNo; // Zero base the col #. - + // Add in the length of the token, so that we cover multi-char tokens. EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts); } else { EndColNo = CaretLine.size(); } } - + // Pick the last non-whitespace column. if (EndColNo <= SourceLine.size()) while (EndColNo-1 && @@ -116,7 +116,7 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, --EndColNo; else EndColNo = SourceLine.size(); - + // Fill the range with ~'s. assert(StartColNo <= EndColNo && "Invalid range!"); for (unsigned i = StartColNo; i < EndColNo; ++i) @@ -156,7 +156,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, for (; FixItStart != FixItEnd; ++FixItStart) if (!isspace(FixItInsertionLine[FixItStart])) break; - + for (; FixItEnd != FixItStart; --FixItEnd) if (!isspace(FixItInsertionLine[FixItEnd - 1])) break; @@ -189,16 +189,16 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, CaretStart = 0; else if (CaretStart > 1) { unsigned NewStart = CaretStart - 1; - + // Skip over any whitespace we see here; we're looking for // another bit of interesting text. while (NewStart && isspace(SourceLine[NewStart])) --NewStart; - + // Skip over this bit of "interesting" text. while (NewStart && !isspace(SourceLine[NewStart])) --NewStart; - + // Move up to the non-whitespace character we just saw. if (NewStart) ++NewStart; @@ -220,7 +220,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, // another bit of interesting text. while (NewEnd != SourceLength && isspace(SourceLine[NewEnd - 1])) ++NewEnd; - + // Skip over this bit of "interesting" text. while (NewEnd != SourceLength && !isspace(SourceLine[NewEnd - 1])) ++NewEnd; @@ -244,7 +244,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, CaretLine.erase(CaretEnd, std::string::npos); if (FixItInsertionLine.size() > CaretEnd) FixItInsertionLine.erase(CaretEnd, std::string::npos); - + if (CaretStart > 2) { SourceLine.replace(0, CaretStart, " ..."); CaretLine.replace(0, CaretStart, " "); @@ -271,7 +271,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns); Loc = SM.getImmediateSpellingLoc(Loc); - + // Map the ranges. for (unsigned i = 0; i != NumRanges; ++i) { SourceLocation S = Ranges[i].getBegin(), E = Ranges[i].getEnd(); @@ -279,10 +279,10 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, if (E.isMacroID()) E = SM.getImmediateSpellingLoc(E); Ranges[i] = SourceRange(S, E); } - + if (ShowLocation) { std::pair<FileID, unsigned> IInfo = SM.getDecomposedInstantiationLoc(Loc); - + // Emit the file/line/column that this expansion came from. OS << SM.getBuffer(IInfo.first)->getBufferIdentifier() << ':' << SM.getLineNumber(IInfo.first, IInfo.second) << ':'; @@ -291,75 +291,75 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, OS << ' '; } OS << "note: instantiated from:\n"; - + EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns); return; } - + // Decompose the location into a FID/Offset pair. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); FileID FID = LocInfo.first; unsigned FileOffset = LocInfo.second; - + // Get information about the buffer it points into. std::pair<const char*, const char*> BufferInfo = SM.getBufferData(FID); const char *BufStart = BufferInfo.first; unsigned ColNo = SM.getColumnNumber(FID, FileOffset); - unsigned CaretEndColNo + unsigned CaretEndColNo = ColNo + Lexer::MeasureTokenLength(Loc, SM, *LangOpts); // Rewind from the current position to the start of the line. const char *TokPtr = BufStart+FileOffset; const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based. - - + + // Compute the line end. Scan forward from the error position to the end of // the line. const char *LineEnd = TokPtr; while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0') ++LineEnd; - + // Copy the line of code into an std::string for ease of manipulation. std::string SourceLine(LineStart, LineEnd); - + // Create a line for the caret that is filled with spaces that is the same // length as the line of source code. std::string CaretLine(LineEnd-LineStart, ' '); - + // Highlight all of the characters covered by Ranges with ~ characters. if (NumRanges) { unsigned LineNo = SM.getLineNumber(FID, FileOffset); - + for (unsigned i = 0, e = NumRanges; i != e; ++i) HighlightRange(Ranges[i], SM, LineNo, FID, CaretLine, SourceLine); } - + // Next, insert the caret itself. if (ColNo-1 < CaretLine.size()) CaretLine[ColNo-1] = '^'; else CaretLine.push_back('^'); - + // Scan the source line, looking for tabs. If we find any, manually expand // them to 8 characters and update the CaretLine to match. for (unsigned i = 0; i != SourceLine.size(); ++i) { if (SourceLine[i] != '\t') continue; - + // Replace this tab with at least one space. SourceLine[i] = ' '; - + // Compute the number of spaces we need to insert. unsigned NumSpaces = ((i+8)&~7) - (i+1); assert(NumSpaces < 8 && "Invalid computation of space amt"); - + // Insert spaces into the SourceLine. SourceLine.insert(i+1, NumSpaces, ' '); - + // Insert spaces or ~'s into CaretLine. CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' '); } - + // If we are in -fdiagnostics-print-source-range-info mode, we are trying to // produce easily machine parsable output. Add a space before the source line // and the caret to make it trivial to tell the main diagnostic line from what @@ -368,7 +368,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, SourceLine = ' ' + SourceLine; CaretLine = ' ' + CaretLine; } - + std::string FixItInsertionLine; if (NumHints && PrintFixItInfo) { for (const CodeModificationHint *Hint = Hints, *LastHint = Hints + NumHints; @@ -376,15 +376,15 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, if (Hint->InsertionLoc.isValid()) { // We have an insertion hint. Determine whether the inserted // code is on the same line as the caret. - std::pair<FileID, unsigned> HintLocInfo + std::pair<FileID, unsigned> HintLocInfo = SM.getDecomposedInstantiationLoc(Hint->InsertionLoc); if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) == SM.getLineNumber(FID, FileOffset)) { // Insert the new code into the line just below the code // that the user wrote. - unsigned HintColNo + unsigned HintColNo = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second); - unsigned LastColumnModified + unsigned LastColumnModified = HintColNo - 1 + Hint->CodeToInsert.size(); if (LastColumnModified > FixItInsertionLine.size()) FixItInsertionLine.resize(LastColumnModified, ' '); @@ -407,7 +407,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, // Finally, remove any blank spaces from the end of CaretLine. while (CaretLine[CaretLine.size()-1] == ' ') CaretLine.erase(CaretLine.end()-1); - + // Emit what we have computed. OS << SourceLine << '\n'; @@ -421,7 +421,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, if (UseColors) // Print fixit line in color OS.changeColor(fixitColor, false); - if (PrintRangeInfo) + if (PrintRangeInfo) OS << ' '; OS << FixItInsertionLine << '\n'; if (UseColors) @@ -435,8 +435,8 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, /// \returns The index of the first non-whitespace character that is /// greater than or equal to Idx or, if no such character exists, /// returns the end of the string. -static unsigned skipWhitespace(unsigned Idx, - const llvm::SmallVectorImpl<char> &Str, +static unsigned skipWhitespace(unsigned Idx, + const llvm::SmallVectorImpl<char> &Str, unsigned Length) { while (Idx < Length && isspace(Str[Idx])) ++Idx; @@ -455,7 +455,7 @@ static inline char findMatchingPunctuation(char c) { case '`': return '\''; case '"': return '"'; case '(': return ')'; - case '[': return ']'; + case '[': return ']'; case '{': return '}'; default: break; } @@ -468,9 +468,9 @@ static inline char findMatchingPunctuation(char c) { /// /// \returns the index pointing one character past the end of the /// word. -unsigned findEndOfWord(unsigned Start, +unsigned findEndOfWord(unsigned Start, const llvm::SmallVectorImpl<char> &Str, - unsigned Length, unsigned Column, + unsigned Length, unsigned Column, unsigned Columns) { unsigned End = Start + 1; @@ -535,13 +535,13 @@ unsigned findEndOfWord(unsigned Start, /// /// \returns true if word-wrapping was required, or false if the /// string fit on the first line. -static bool PrintWordWrapped(llvm::raw_ostream &OS, - const llvm::SmallVectorImpl<char> &Str, - unsigned Columns, +static bool PrintWordWrapped(llvm::raw_ostream &OS, + const llvm::SmallVectorImpl<char> &Str, + unsigned Columns, unsigned Column = 0, unsigned Indentation = WordWrapIndentation) { unsigned Length = Str.size(); - + // If there is a newline in this message somewhere, find that // newline and split the message into the part before the newline // (which will be word-wrapped) and the part from the newline one @@ -556,7 +556,7 @@ static bool PrintWordWrapped(llvm::raw_ostream &OS, llvm::SmallString<16> IndentStr; IndentStr.assign(Indentation, ' '); bool Wrapped = false; - for (unsigned WordStart = 0, WordEnd; WordStart < Length; + for (unsigned WordStart = 0, WordEnd; WordStart < Length; WordStart = WordEnd) { // Find the beginning of the next word. WordStart = skipWhitespace(WordStart, Str, Length); @@ -565,7 +565,7 @@ static bool PrintWordWrapped(llvm::raw_ostream &OS, // Find the end of this word. WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns); - + // Does this word fit on the current line? unsigned WordLength = WordEnd - WordStart; if (Column + WordLength < Columns) { @@ -587,7 +587,7 @@ static bool PrintWordWrapped(llvm::raw_ostream &OS, Column = Indentation + WordLength; Wrapped = true; } - + if (Length == Str.size()) return Wrapped; // We're done. @@ -597,7 +597,7 @@ static bool PrintWordWrapped(llvm::raw_ostream &OS, return true; } -void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, +void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info) { // Keeps track of the the starting position of the location // information (e.g., "foo.c:10:4:") that precedes the error @@ -611,7 +611,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, const SourceManager &SM = Info.getLocation().getManager(); PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation()); unsigned LineNo = PLoc.getLine(); - + // First, if this diagnostic is not in the main file, print out the // "included from" lines. if (LastWarningLoc != PLoc.getIncludeLoc()) { @@ -619,7 +619,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, PrintIncludeStack(LastWarningLoc, SM); StartOfLocationInfo = OS.tell(); } - + // Compute the column number. if (ShowLocation) { if (UseColors) @@ -628,12 +628,12 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, if (ShowColumn) if (unsigned ColNo = PLoc.getColumn()) OS << ColNo << ':'; - + if (PrintRangeInfo && Info.getNumRanges()) { FileID CaretFileID = SM.getFileID(SM.getInstantiationLoc(Info.getLocation())); bool PrintedRange = false; - + for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) { // Ignore invalid ranges. if (!Info.getRange(i).isValid()) continue; @@ -642,7 +642,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, SourceLocation E = Info.getRange(i).getEnd(); B = SM.getInstantiationLoc(B); E = SM.getInstantiationLoc(E); - + // If the End location and the start location are the same and are a // macro location, then the range was something that came from a macro // expansion or _Pragma. If this is an object-like macro, the best we @@ -653,22 +653,22 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); - + // If the start or end of the range is in another file, just discard // it. if (BInfo.first != CaretFileID || EInfo.first != CaretFileID) continue; - + // Add in the length of the token, so that we cover multi-char tokens. unsigned TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts); - + OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':' << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' << SM.getLineNumber(EInfo.first, EInfo.second) << ':' << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) << '}'; PrintedRange = true; } - + if (PrintedRange) OS << ':'; } @@ -688,7 +688,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, case Diagnostic::Fatal: OS.changeColor(fatalColor, true); break; } } - + switch (Level) { case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type"); case Diagnostic::Note: OS << "note: "; break; @@ -702,14 +702,14 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, llvm::SmallString<100> OutStr; Info.FormatDiagnostic(OutStr); - + if (PrintDiagnosticOption) if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) { OutStr += " [-W"; OutStr += Opt; OutStr += ']'; } - + if (UseColors) { // Print warnings, errors and fatal errors in bold, no color switch (Level) { @@ -732,7 +732,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, OS << '\n'; if (UseColors) OS.resetColor(); - + // If caret diagnostics are enabled and we have location, we want to // emit the caret. However, we only do this if the location moved // from the last diagnostic, if the last diagnostic was a note that @@ -740,7 +740,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, // diagnostic has ranges. We don't want to emit the same caret // multiple times if one loc has multiple diagnostics. if (CaretDiagnostics && Info.getLocation().isValid() && - ((LastLoc != Info.getLocation()) || Info.getNumRanges() || + ((LastLoc != Info.getLocation()) || Info.getNumRanges() || (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) || Info.getNumCodeModificationHints())) { // Cache the LastLoc, it allows us to omit duplicate source/caret spewage. @@ -753,7 +753,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, assert(NumRanges < 20 && "Out of space"); for (unsigned i = 0; i != NumRanges; ++i) Ranges[i] = Info.getRange(i); - + unsigned NumHints = Info.getNumCodeModificationHints(); for (unsigned idx = 0; idx < NumHints; ++idx) { const CodeModificationHint &Hint = Info.getCodeModificationHint(idx); @@ -768,6 +768,6 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, Info.getNumCodeModificationHints(), MessageLength); } - + OS.flush(); } diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp index f32fbbd2413b..8bd05443a7fe 100644 --- a/lib/Frontend/TypeXML.cpp +++ b/lib/Frontend/TypeXML.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the XML document class, which provides the means to +// This file implements the XML document class, which provides the means to // dump out the AST in a XML form that exposes type details and other fields. // //===----------------------------------------------------------------------===// @@ -21,38 +21,36 @@ namespace clang { namespace XML { namespace { -//--------------------------------------------------------- -class TypeWriter : public TypeVisitor<TypeWriter> -{ +//--------------------------------------------------------- +class TypeWriter : public TypeVisitor<TypeWriter> { DocumentXML& Doc; public: TypeWriter(DocumentXML& doc) : Doc(doc) {} #define NODE_XML( CLASS, NAME ) \ - void Visit##CLASS(CLASS* T) \ - { \ - Doc.addSubNode(NAME); + void Visit##CLASS(CLASS* T) { \ + Doc.addSubNode(NAME); #define ID_ATTRIBUTE_XML // done by the Document class itself -#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); #define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") #define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); #define ATTRIBUTE_ENUM_XML( FN, NAME ) \ { \ const char* pAttributeName = NAME; \ const bool optional = false; \ switch (T->FN) { \ - default: assert(0 && "unknown enum value"); + default: assert(0 && "unknown enum value"); #define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ { \ const char* pAttributeName = NAME; \ const bool optional = true; \ switch (T->FN) { \ - default: assert(0 && "unknown enum value"); + default: assert(0 && "unknown enum value"); #define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; #define END_ENUM_XML } } @@ -62,22 +60,19 @@ public: }; -//--------------------------------------------------------- +//--------------------------------------------------------- } // anon clang } // NS XML -//--------------------------------------------------------- -class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder> -{ +//--------------------------------------------------------- +class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder> { DocumentXML& Doc; - void addIfType(const Type* pType) - { + void addIfType(const Type* pType) { Doc.addTypeRecursively(pType); } - void addIfType(const QualType& pType) - { + void addIfType(const QualType& pType) { Doc.addTypeRecursively(pType); } @@ -88,40 +83,37 @@ public: #define NODE_XML( CLASS, NAME ) \ void Visit##CLASS(CLASS* T) \ - { - -#define ID_ATTRIBUTE_XML -#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN); -#define CONTEXT_ATTRIBUTE_XML( FN ) -#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN); -#define ATTRIBUTE_OPT_XML( FN, NAME ) -#define ATTRIBUTE_ENUM_XML( FN, NAME ) -#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) -#define ENUM_XML( VALUE, NAME ) -#define END_ENUM_XML + { + +#define ID_ATTRIBUTE_XML +#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN); +#define CONTEXT_ATTRIBUTE_XML( FN ) +#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN); +#define ATTRIBUTE_OPT_XML( FN, NAME ) +#define ATTRIBUTE_ENUM_XML( FN, NAME ) +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) +#define ENUM_XML( VALUE, NAME ) +#define END_ENUM_XML #define END_NODE_XML } #include "clang/Frontend/TypeXML.def" }; -//--------------------------------------------------------- -void DocumentXML::addParentTypes(const Type* pType) -{ +//--------------------------------------------------------- +void DocumentXML::addParentTypes(const Type* pType) { TypeAdder(*this).Visit(const_cast<Type*>(pType)); } -//--------------------------------------------------------- -void DocumentXML::writeTypeToXML(const Type* pType) -{ +//--------------------------------------------------------- +void DocumentXML::writeTypeToXML(const Type* pType) { XML::TypeWriter(*this).Visit(const_cast<Type*>(pType)); } -//--------------------------------------------------------- -void DocumentXML::writeTypeToXML(const QualType& pType) -{ +//--------------------------------------------------------- +void DocumentXML::writeTypeToXML(const QualType& pType) { XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType)); } -//--------------------------------------------------------- +//--------------------------------------------------------- } // NS clang diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp index c8fd5f6fcbc0..7b01b0fb7416 100644 --- a/lib/Frontend/Warnings.cpp +++ b/lib/Frontend/Warnings.cpp @@ -47,7 +47,7 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags, Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Warn); else Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Ignore); - + // FIXME: -Wfatal-errors / -Wfatal-errors=foo for (unsigned i = 0, e = Warnings.size(); i != e; ++i) { @@ -55,7 +55,7 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags, const char *OptStart = &Opt[0]; const char *OptEnd = OptStart+Opt.size(); assert(*OptEnd == 0 && "Expect null termination for lower-bound search"); - + // Check to see if this warning starts with "no-", if so, this is a negative // form of the option. bool isPositive = true; @@ -74,7 +74,7 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags, Diags.setSuppressSystemWarnings(!isPositive); continue; } - + // -Werror/-Wno-error is a special case, not controlled by the option table. // It also has the "specifier" form of -Werror=foo and -Werror-foo. if (OptEnd-OptStart >= 5 && memcmp(OptStart, "error", 5) == 0) { @@ -88,21 +88,21 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags, } Specifier = OptStart+6; } - + if (Specifier == 0) { - Diags.setWarningsAsErrors(true); + Diags.setWarningsAsErrors(isPositive); continue; } - + // -Werror=foo maps foo to Error, -Wno-error=foo maps it to Warning. Mapping = isPositive ? diag::MAP_ERROR : diag::MAP_WARNING_NO_WERROR; OptStart = Specifier; } - + if (Diags.setDiagnosticGroupMapping(OptStart, Mapping)) Diags.Report(FullSourceLoc(), diag::warn_unknown_warning_option) << ("-W" + Opt); } - + return false; } |