diff options
Diffstat (limited to 'lib/Frontend')
28 files changed, 1215 insertions, 204 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index e3cd6dd..f647c8a 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -14,25 +14,28 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/PCHReader.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Diagnostic.h" -#include "llvm/Support/Compiler.h" +#include "llvm/LLVMContext.h" #include "llvm/System/Path.h" - using namespace clang; -ASTUnit::ASTUnit(DiagnosticClient *diagClient) : tempFile(false) { +ASTUnit::ASTUnit(DiagnosticClient *diagClient) : tempFile(false) { Diags.setClient(diagClient ? diagClient : new TextDiagnosticBuffer()); } -ASTUnit::~ASTUnit() { +ASTUnit::~ASTUnit() { if (tempFile) llvm::sys::Path(getPCHFileName()).eraseFromDisk(); - + // The ASTUnit object owns the DiagnosticClient. delete Diags.getClient(); } @@ -41,7 +44,7 @@ namespace { /// \brief Gathers information from PCHReader that will be used to initialize /// a Preprocessor. -class VISIBILITY_HIDDEN PCHInfoCollector : public PCHReaderListener { +class PCHInfoCollector : public PCHReaderListener { LangOptions &LangOpt; HeaderSearch &HSI; std::string &TargetTriple; @@ -171,3 +174,90 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, return AST.take(); } + +namespace { + +class NullAction : public ASTFrontendAction { + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) { + return new ASTConsumer(); + } + +public: + virtual bool hasCodeCompletionSupport() const { return false; } +}; + +} + +ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI, + Diagnostic &Diags, + bool OnlyLocalDecls, + bool UseBumpAllocator) { + // Create the compiler instance to use for building the AST. + CompilerInstance Clang(&llvm::getGlobalContext(), false); + llvm::OwningPtr<ASTUnit> AST; + NullAction Act; + + Clang.getInvocation() = CI; + + Clang.setDiagnostics(&Diags); + Clang.setDiagnosticClient(Diags.getClient()); + + // Create the target instance. + Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(), + Clang.getTargetOpts())); + if (!Clang.hasTarget()) + goto error; + + // Inform the target of the language options. + // + // FIXME: We shouldn't need to do this, the target should be immutable once + // created. This complexity should be lifted elsewhere. + Clang.getTarget().setForcedLangOptions(Clang.getLangOpts()); + + assert(Clang.getFrontendOpts().Inputs.size() == 1 && + "Invocation must have exactly one source file!"); + assert(Clang.getFrontendOpts().Inputs[0].first != FrontendOptions::IK_AST && + "FIXME: AST inputs not yet supported here!"); + + // Create the AST unit. + // + // FIXME: Use the provided diagnostic client. + AST.reset(new ASTUnit()); + + // Create a file manager object to provide access to and cache the filesystem. + Clang.setFileManager(&AST->getFileManager()); + + // Create the source manager. + Clang.setSourceManager(&AST->getSourceManager()); + + // Create the preprocessor. + Clang.createPreprocessor(); + + if (!Act.BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second, + /*IsAST=*/false)) + goto error; + + Act.Execute(); + + // Steal the created context and preprocessor, and take back the source and + // file managers. + AST->Ctx.reset(Clang.takeASTContext()); + AST->PP.reset(Clang.takePreprocessor()); + Clang.takeSourceManager(); + Clang.takeFileManager(); + + Act.EndSourceFile(); + + Clang.takeDiagnosticClient(); + Clang.takeDiagnostics(); + + return AST.take(); + +error: + Clang.takeSourceManager(); + Clang.takeFileManager(); + Clang.takeDiagnosticClient(); + Clang.takeDiagnostics(); + return 0; +} diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index ede3d47..5df1ece 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -30,7 +30,6 @@ #include "clang/Basic/SourceManager.h" #include "clang/Frontend/PathDiagnosticClients.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" #include "llvm/System/Program.h" @@ -62,7 +61,7 @@ CreatePlistHTMLDiagnosticClient(const std::string& prefix, namespace { - class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer { + class AnalysisConsumer : public ASTConsumer { public: typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D); @@ -312,7 +311,8 @@ static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr, } -static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D, +static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, + Decl *D, GRTransferFuncs* tf) { llvm::OwningPtr<GRTransferFuncs> TF(tf); @@ -327,10 +327,6 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl * return; GRExprEngine Eng(mgr); - - Eng.setTransferFunctions(tf); - Eng.RegisterInternalChecks(); // FIXME: Internal checks should just - // automatically register. if (C.Opts.EnableExperimentalInternalChecks) RegisterExperimentalInternalChecks(Eng); @@ -339,6 +335,8 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl * if (C.Opts.EnableExperimentalChecks) RegisterExperimentalChecks(Eng); + + Eng.setTransferFunctions(tf); // Set the graph auditor. llvm::OwningPtr<ExplodedNode::Auditor> Auditor; @@ -455,26 +453,8 @@ static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr, static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr, Decl *D) { - if (!D) - return; - - C.DisplayFunction(D); - llvm::OwningPtr<GRTransferFuncs> TF(CreateCallInliner(mgr.getASTContext())); - - // Construct the analysis engine. - GRExprEngine Eng(mgr); - - Eng.setTransferFunctions(TF.get()); - 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()); + ActionGRExprEngine(C, mgr, D, CreateCallInliner(mgr.getASTContext())); } //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp index bc56029..9dc109d 100644 --- a/lib/Frontend/Backend.cpp +++ b/lib/Frontend/Backend.cpp @@ -25,12 +25,9 @@ #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.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" -#include "llvm/System/Program.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -39,10 +36,11 @@ using namespace clang; using namespace llvm; namespace { - class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer { + class BackendConsumer : public ASTConsumer { BackendAction Action; - CodeGenOptions CodeGenOpts; - TargetOptions TargetOpts; + const CodeGenOptions &CodeGenOpts; + const LangOptions &LangOpts; + const TargetOptions &TargetOpts; llvm::raw_ostream *AsmOutStream; llvm::formatted_raw_ostream FormattedOutStream; ASTContext *Context; @@ -78,10 +76,12 @@ namespace { public: BackendConsumer(BackendAction action, Diagnostic &Diags, const LangOptions &langopts, const CodeGenOptions &compopts, - const TargetOptions &targetopts, const std::string &infile, - llvm::raw_ostream* OS, LLVMContext& C) : + const TargetOptions &targetopts, bool TimePasses, + const std::string &infile, llvm::raw_ostream *OS, + LLVMContext& C) : Action(action), CodeGenOpts(compopts), + LangOpts(langopts), TargetOpts(targetopts), AsmOutStream(OS), LLVMIRGeneration("LLVM IR Generation Time"), @@ -94,8 +94,7 @@ namespace { FormattedOutStream.setStream(*AsmOutStream, formatted_raw_ostream::PRESERVE_STREAM); - // Enable -time-passes if -ftime-report is enabled. - llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesIsEnabled = TimePasses; } ~BackendConsumer() { @@ -109,7 +108,7 @@ namespace { virtual void Initialize(ASTContext &Ctx) { Context = &Ctx; - if (CodeGenOpts.TimePasses) + if (llvm::TimePassesIsEnabled) LLVMIRGeneration.startTimer(); Gen->Initialize(Ctx); @@ -118,7 +117,7 @@ namespace { ModuleProvider = new ExistingModuleProvider(TheModule); TheTargetData = new llvm::TargetData(Ctx.Target.getTargetDescription()); - if (CodeGenOpts.TimePasses) + if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); } @@ -127,24 +126,24 @@ namespace { Context->getSourceManager(), "LLVM IR generation of declaration"); - if (CodeGenOpts.TimePasses) + if (llvm::TimePassesIsEnabled) LLVMIRGeneration.startTimer(); Gen->HandleTopLevelDecl(D); - if (CodeGenOpts.TimePasses) + if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); } virtual void HandleTranslationUnit(ASTContext &C) { { PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); - if (CodeGenOpts.TimePasses) + if (llvm::TimePassesIsEnabled) LLVMIRGeneration.startTimer(); Gen->HandleTranslationUnit(C); - if (CodeGenOpts.TimePasses) + if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); } @@ -215,11 +214,50 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) { return false; } + // FIXME: Expose these capabilities via actual APIs!!!! Aside from just + // being gross, this is also totally broken if we ever care about + // concurrency. + std::vector<const char *> BackendArgs; + BackendArgs.push_back("clang"); // Fake program name. + if (CodeGenOpts.AsmVerbose) + BackendArgs.push_back("-asm-verbose"); + if (!CodeGenOpts.CodeModel.empty()) { + BackendArgs.push_back("-code-model"); + BackendArgs.push_back(CodeGenOpts.CodeModel.c_str()); + } + if (!CodeGenOpts.DebugPass.empty()) { + BackendArgs.push_back("-debug-pass"); + BackendArgs.push_back(CodeGenOpts.DebugPass.c_str()); + } + if (CodeGenOpts.DisableFPElim) + BackendArgs.push_back("-disable-fp-elim"); + if (!CodeGenOpts.FloatABI.empty()) { + BackendArgs.push_back("-float-abi"); + BackendArgs.push_back(CodeGenOpts.FloatABI.c_str()); + } + if (!CodeGenOpts.LimitFloatPrecision.empty()) { + BackendArgs.push_back("-limit-float-precision"); + BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str()); + } + if (CodeGenOpts.NoZeroInitializedInBSS) + BackendArgs.push_back("-nozero-initialized-in-bss"); + if (CodeGenOpts.SoftFloat) + BackendArgs.push_back("-soft-float"); + BackendArgs.push_back("-relocation-model"); + BackendArgs.push_back(CodeGenOpts.RelocationModel.c_str()); + if (llvm::TimePassesIsEnabled) + BackendArgs.push_back("-time-passes"); + if (CodeGenOpts.UnwindTables) + BackendArgs.push_back("-unwind-tables"); + BackendArgs.push_back(0); + llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, + (char**) &BackendArgs[0]); + std::string FeaturesStr; if (TargetOpts.CPU.size() || TargetOpts.Features.size()) { SubtargetFeatures Features; Features.setCPU(TargetOpts.CPU); - for (std::vector<std::string>::iterator + for (std::vector<std::string>::const_iterator it = TargetOpts.Features.begin(), ie = TargetOpts.Features.end(); it != ie; ++it) Features.AddFeature(*it); @@ -306,7 +344,7 @@ void BackendConsumer::CreatePasses() { llvm::createStandardModulePasses(PM, OptLevel, CodeGenOpts.OptimizeSize, CodeGenOpts.UnitAtATime, CodeGenOpts.UnrollLoops, - CodeGenOpts.SimplifyLibCalls, + /*SimplifyLibCalls=*/!LangOpts.NoBuiltin, /*HaveExceptions=*/true, InliningPass); } @@ -318,7 +356,7 @@ void BackendConsumer::EmitAssembly() { if (!TheModule || !TheTargetData) return; - TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : 0); + TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : 0); // Make sure IR generation is happy with the module. This is // released by the module provider. @@ -375,9 +413,10 @@ ASTConsumer *clang::CreateBackendConsumer(BackendAction Action, const LangOptions &LangOpts, const CodeGenOptions &CodeGenOpts, const TargetOptions &TargetOpts, + bool TimePasses, const std::string& InFile, llvm::raw_ostream* OS, LLVMContext& C) { return new BackendConsumer(Action, Diags, LangOpts, CodeGenOpts, - TargetOpts, InFile, OS, C); + TargetOpts, TimePasses, InFile, OS, C); } diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 3f0f430..03123d3 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -21,6 +21,7 @@ add_clang_library(clangFrontend HTMLPrint.cpp InitHeaderSearch.cpp InitPreprocessor.cpp + LangStandards.cpp PCHReader.cpp PCHReaderDecl.cpp PCHReaderStmt.cpp diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 339a1c4..7296246 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -22,7 +22,6 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/StringExtras.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" @@ -40,7 +39,7 @@ using namespace clang::io; //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN PTHEntry { +class PTHEntry { Offset TokenData, PPCondData; public: @@ -54,7 +53,7 @@ public: }; -class VISIBILITY_HIDDEN PTHEntryKeyVariant { +class PTHEntryKeyVariant { union { const FileEntry* FE; const char* Path; }; enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind; struct stat *StatBuf; @@ -105,7 +104,7 @@ public: } }; -class VISIBILITY_HIDDEN FileEntryPTHEntryInfo { +class FileEntryPTHEntryInfo { public: typedef PTHEntryKeyVariant key_type; typedef key_type key_type_ref; @@ -169,7 +168,7 @@ typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap; typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy; namespace { -class VISIBILITY_HIDDEN PTHWriter { +class PTHWriter { IDMap IM; llvm::raw_fd_ostream& Out; Preprocessor& PP; @@ -483,7 +482,8 @@ void PTHWriter::GeneratePTH(const std::string *MainFile) { if (!B) continue; FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); - Lexer L(FID, SM, LOpts); + const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID); + Lexer L(FID, FromFile, SM, LOpts); PM.insert(FE, LexTokens(L)); } @@ -577,7 +577,7 @@ public: }; namespace { -class VISIBILITY_HIDDEN PTHIdentifierTableTrait { +class PTHIdentifierTableTrait { public: typedef PTHIdKey* key_type; typedef key_type key_type_ref; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 0365761..1083d5e 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -27,7 +27,9 @@ #include "llvm/LLVMContext.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Timer.h" #include "llvm/System/Path.h" +#include "llvm/System/Program.h" using namespace clang; CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext, @@ -255,6 +257,16 @@ void CompilerInstance::createCodeCompletionConsumer() { getFrontendOpts().DebugCodeCompletionPrinter, getFrontendOpts().ShowMacrosInCodeCompletion, llvm::outs())); + + if (CompletionConsumer->isOutputBinary() && + llvm::sys::Program::ChangeStdoutToBinary()) { + getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); + CompletionConsumer.reset(); + } +} + +void CompilerInstance::createFrontendTimer() { + FrontendTimer.reset(new llvm::Timer("Clang front-end timer")); } CodeCompleteConsumer * @@ -321,7 +333,7 @@ CompilerInstance::createOutputFile(llvm::StringRef OutputPath, &OutputPathName); if (!OS) { // FIXME: Don't fail this way. - llvm::errs() << "ERROR: " << Error << "\n"; + llvm::errs() << "error: " << Error << "\n"; ::exit(1); } @@ -353,16 +365,16 @@ CompilerInstance::createOutputFile(llvm::StringRef OutputPath, OutFile = "-"; } - llvm::raw_fd_ostream *OS = + llvm::OwningPtr<llvm::raw_fd_ostream> OS( new llvm::raw_fd_ostream(OutFile.c_str(), Error, - (Binary ? llvm::raw_fd_ostream::F_Binary : 0)); - if (!OS) + (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); + if (!Error.empty()) return 0; if (ResultPathName) *ResultPathName = OutFile; - return OS; + return OS.take(); } // Initialization Utilities diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index b4a79c6..c537507 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -8,20 +8,32 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/Version.h" +#include "clang/Driver/Arg.h" +#include "clang/Driver/ArgList.h" +#include "clang/Driver/CC1Options.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/OptTable.h" +#include "clang/Driver/Option.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/LangStandard.h" +#include "clang/Frontend/PCHReader.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/System/Host.h" +#include "llvm/System/Path.h" using namespace clang; -void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, - const llvm::SmallVectorImpl<llvm::StringRef> &Args) { -} - static const char *getAnalysisName(Analyses Kind) { switch (Kind) { default: llvm::llvm_unreachable("Unknown analysis store!"); #define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\ - case NAME: return CMDFLAG; + case NAME: return "-" CMDFLAG; #include "clang/Frontend/Analyses.def" } } @@ -56,6 +68,10 @@ static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) { } } +//===----------------------------------------------------------------------===// +// Serialization (to args) +//===----------------------------------------------------------------------===// + static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, std::vector<std::string> &Res) { for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i) @@ -93,7 +109,7 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, if (Opts.EnableExperimentalChecks) Res.push_back("-analyzer-experimental-checks"); if (Opts.EnableExperimentalInternalChecks) - Res.push_back("-analyzer-experimental-internal-checls"); + Res.push_back("-analyzer-experimental-internal-checks"); } static void CodeGenOptsToArgs(const CodeGenOptions &Opts, @@ -106,20 +122,56 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-disable-red-zone"); if (!Opts.MergeAllConstants) Res.push_back("-fno-merge-all-constants"); - // NoCommon is only derived. + if (Opts.NoCommon) + Res.push_back("-fno-common"); if (Opts.NoImplicitFloat) Res.push_back("-no-implicit-float"); if (Opts.OptimizeSize) { assert(Opts.OptimizationLevel == 2 && "Invalid options!"); Res.push_back("-Os"); - } else if (Opts.OptimizationLevel == 0) - Res.push_back("-O" + Opts.OptimizationLevel); + } else if (Opts.OptimizationLevel != 0) + Res.push_back("-O" + llvm::utostr(Opts.OptimizationLevel)); + if (!Opts.MainFileName.empty()) { + Res.push_back("-main-file-name"); + Res.push_back(Opts.MainFileName); + } // SimplifyLibCalls is only derived. // TimePasses is only derived. // UnitAtATime is unused. // UnrollLoops is only derived. // VerifyModule is only derived. // Inlining is only derived. + + if (Opts.AsmVerbose) + Res.push_back("-masm-verbose"); + if (!Opts.CodeModel.empty()) { + Res.push_back("-mcode-model"); + Res.push_back(Opts.CodeModel); + } + if (!Opts.DebugPass.empty()) { + Res.push_back("-mdebug-pass"); + Res.push_back(Opts.DebugPass); + } + if (Opts.DisableFPElim) + Res.push_back("-mdisable-fp-elim"); + if (!Opts.FloatABI.empty()) { + Res.push_back("-mfloat-abi"); + Res.push_back(Opts.FloatABI); + } + if (!Opts.LimitFloatPrecision.empty()) { + Res.push_back("-mlimit-float-precision"); + Res.push_back(Opts.LimitFloatPrecision); + } + if (Opts.NoZeroInitializedInBSS) + Res.push_back("-mno-zero-initialized-bss"); + if (Opts.SoftFloat) + Res.push_back("-msoft-float"); + if (Opts.UnwindTables) + Res.push_back("-munwind-tables"); + if (Opts.RelocationModel != "pic") { + Res.push_back("-mrelocation-model"); + Res.push_back(Opts.RelocationModel); + } } static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts, @@ -178,18 +230,18 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, static const char *getInputKindName(FrontendOptions::InputKind Kind) { switch (Kind) { - case FrontendOptions::IK_None: break; - case FrontendOptions::IK_AST: return "ast"; - case FrontendOptions::IK_Asm: return "assembler-with-cpp"; - case FrontendOptions::IK_C: return "c"; - case FrontendOptions::IK_CXX: return "c++"; - case FrontendOptions::IK_ObjC: return "objective-c"; - case FrontendOptions::IK_ObjCXX: return "objective-c++"; - case FrontendOptions::IK_OpenCL: return "cl"; - case FrontendOptions::IK_PreprocessedC: return "cpp-output"; - case FrontendOptions::IK_PreprocessedCXX: return "c++-cpp-output"; - case FrontendOptions::IK_PreprocessedObjC: return "objective-c-cpp-output"; - case FrontendOptions::IK_PreprocessedObjCXX: return "objective-c++-cpp-output"; + case FrontendOptions::IK_None: break; + case FrontendOptions::IK_AST: return "ast"; + case FrontendOptions::IK_Asm: return "assembler-with-cpp"; + case FrontendOptions::IK_C: return "c"; + case FrontendOptions::IK_CXX: return "c++"; + case FrontendOptions::IK_ObjC: return "objective-c"; + case FrontendOptions::IK_ObjCXX: return "objective-c++"; + case FrontendOptions::IK_OpenCL: return "cl"; + case FrontendOptions::IK_PreprocessedC: return "cpp-output"; + case FrontendOptions::IK_PreprocessedCXX: return "c++-cpp-output"; + case FrontendOptions::IK_PreprocessedObjC: return "objective-c-cpp-output"; + case FrontendOptions::IK_PreprocessedObjCXX:return "objective-c++-cpp-output"; } llvm::llvm_unreachable("Unexpected language kind!"); @@ -247,7 +299,7 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, if (Opts.ShowMacrosInCodeCompletion) Res.push_back("-code-completion-macros"); if (Opts.ShowStats) - Res.push_back("-stats"); + Res.push_back("-print-stats"); if (Opts.ShowTimers) Res.push_back("-ftime-report"); @@ -305,13 +357,13 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, /// User specified include entries. for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) { const HeaderSearchOptions::Entry &E = Opts.UserEntries[i]; - if (E.IsFramework && (E.Group != frontend::Angled || E.IsUserSupplied)) + if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied)) llvm::llvm_report_error("Invalid option set!"); if (E.IsUserSupplied) { if (E.Group == frontend::After) { Res.push_back("-idirafter"); } else if (E.Group == frontend::Quoted) { - Res.push_back("-iquoted"); + Res.push_back("-iquote"); } else if (E.Group == frontend::System) { Res.push_back("-isystem"); } else { @@ -391,8 +443,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fno-lax-vector-conversions"); if (Opts.AltiVec) Res.push_back("-faltivec"); - Res.push_back("-fexceptions"); - Res.push_back(Opts.Exceptions ? "1" : "0"); + if (Opts.Exceptions) + Res.push_back("-fexceptions"); if (!Opts.Rtti) Res.push_back("-fno-rtti"); if (!Opts.NeXTRuntime) @@ -406,7 +458,7 @@ static void LangOptsToArgs(const LangOptions &Opts, if (Opts.POSIXThreads) Res.push_back("-pthread"); if (Opts.Blocks) - Res.push_back("-fblocks=1"); + Res.push_back("-fblocks"); if (Opts.EmitAllDecls) Res.push_back("-femit-all-decls"); if (!Opts.MathErrno) @@ -425,12 +477,13 @@ static void LangOptsToArgs(const LangOptions &Opts, } if (Opts.ObjCGCBitmapPrint) Res.push_back("-print-ivar-layout"); - Res.push_back("-faccess-control"); - Res.push_back(Opts.AccessControl ? "1" : "0"); - Res.push_back("-fsigned-char"); - Res.push_back(Opts.CharIsSigned ? "1" : "0"); - Res.push_back("-fshort-wchar"); - Res.push_back(Opts.ShortWChar ? "1" : "0"); + // FIXME: Don't forget to update when the default changes! + if (Opts.AccessControl) + Res.push_back("-faccess-control"); + if (!Opts.CharIsSigned) + Res.push_back("-fno-signed-char"); + if (Opts.ShortWChar) + Res.push_back("-fshort-wchar"); if (!Opts.ElideConstructors) Res.push_back("-fno-elide-constructors"); if (Opts.getGCMode() != LangOptions::NonGC) { @@ -444,7 +497,7 @@ static void LangOptsToArgs(const LangOptions &Opts, if (Opts.getVisibilityMode() != LangOptions::Default) { Res.push_back("-fvisibility"); if (Opts.getVisibilityMode() == LangOptions::Hidden) { - Res.push_back("default"); + Res.push_back("hidden"); } else { assert(Opts.getVisibilityMode() == LangOptions::Protected && "Invalid visibility!"); @@ -455,15 +508,11 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-stack-protector"); Res.push_back(llvm::utostr(Opts.getStackProtectorMode())); } - if (Opts.getMainFileName()) { - Res.push_back("-main-file-name"); - Res.push_back(Opts.getMainFileName()); - } if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth) { Res.push_back("-ftemplate-depth"); Res.push_back(llvm::utostr(Opts.InstantiationDepth)); } - if (Opts.ObjCConstantStringClass) { + if (!Opts.ObjCConstantStringClass.empty()) { Res.push_back("-fconstant-string-class"); Res.push_back(Opts.ObjCConstantStringClass); } @@ -472,28 +521,34 @@ static void LangOptsToArgs(const LangOptions &Opts, static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts, std::vector<std::string> &Res) { for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i) - Res.push_back((Opts.Macros[i].second ? "-U" : "-D") + Opts.Macros[i].first); + Res.push_back(std::string(Opts.Macros[i].second ? "-U" : "-D") + + Opts.Macros[i].first); for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) { + // FIXME: We need to avoid reincluding the implicit PCH and PTH includes. Res.push_back("-include"); Res.push_back(Opts.Includes[i]); } for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i) { Res.push_back("-imacros"); - Res.push_back(Opts.Includes[i]); + Res.push_back(Opts.MacroIncludes[i]); } if (!Opts.UsePredefines) Res.push_back("-undef"); if (!Opts.ImplicitPCHInclude.empty()) { - Res.push_back("-implicit-pch-include"); + Res.push_back("-include-pch"); Res.push_back(Opts.ImplicitPCHInclude); } if (!Opts.ImplicitPTHInclude.empty()) { - Res.push_back("-implicit-pth-include"); + Res.push_back("-include-pth"); Res.push_back(Opts.ImplicitPTHInclude); } if (!Opts.TokenCache.empty()) { - Res.push_back("-token-cache"); - Res.push_back(Opts.TokenCache); + if (Opts.ImplicitPTHInclude.empty()) { + Res.push_back("-token-cache"); + Res.push_back(Opts.TokenCache); + } else + assert(Opts.ImplicitPTHInclude == Opts.TokenCache && + "Unsupported option combination!"); } } @@ -520,7 +575,7 @@ static void TargetOptsToArgs(const TargetOptions &Opts, Res.push_back("-triple"); Res.push_back(Opts.Triple); if (!Opts.CPU.empty()) { - Res.push_back("-target-cpu"); + Res.push_back("-mcpu"); Res.push_back(Opts.CPU); } if (!Opts.ABI.empty()) { @@ -545,3 +600,663 @@ void CompilerInvocation::toArgs(std::vector<std::string> &Res) { PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), Res); TargetOptsToArgs(getTargetOpts(), Res); } + +//===----------------------------------------------------------------------===// +// Deserialization (to args) +//===----------------------------------------------------------------------===// + +using namespace clang::driver; +using namespace clang::driver::cc1options; + +static llvm::StringRef getLastArgValue(ArgList &Args, cc1options::ID ID, + llvm::StringRef Default = "") { + if (Arg *A = Args.getLastArg(ID)) + return A->getValue(Args); + return Default; +} + +static int getLastArgIntValue(ArgList &Args, cc1options::ID ID, + int Default, Diagnostic &Diags) { + Arg *A = Args.getLastArg(ID); + if (!A) + return Default; + + int Res = Default; + if (llvm::StringRef(A->getValue(Args)).getAsInteger(10, Res)) + Diags.Report(diag::err_drv_invalid_int_value) + << A->getAsString(Args) << A->getValue(Args); + + return Res; +} + +static std::vector<std::string> +getAllArgValues(ArgList &Args, cc1options::ID ID) { + llvm::SmallVector<const char *, 16> Values; + Args.AddAllArgValues(Values, ID); + return std::vector<std::string>(Values.begin(), Values.end()); +} + +// + +static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, + Diagnostic &Diags) { + using namespace cc1options; + + Opts.AnalysisList.clear(); +#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) \ + if (Args.hasArg(OPT_analysis_##NAME)) Opts.AnalysisList.push_back(NAME); +#include "clang/Frontend/Analyses.def" + + if (Arg *A = Args.getLastArg(OPT_analyzer_store)) { + llvm::StringRef Name = A->getValue(Args); + AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name) +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \ + .Case(CMDFLAG, NAME##Model) +#include "clang/Frontend/Analyses.def" + .Default(NumStores); + // FIXME: Error handling. + if (Value == NumStores) + Diags.Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_O)->getAsString(Args) << Name; + else + Opts.AnalysisStoreOpt = Value; + } + + if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) { + llvm::StringRef Name = A->getValue(Args); + AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name) +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \ + .Case(CMDFLAG, NAME##Model) +#include "clang/Frontend/Analyses.def" + .Default(NumConstraints); + // FIXME: Error handling. + if (Value == NumConstraints) + Diags.Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_O)->getAsString(Args) << Name; + else + Opts.AnalysisConstraintsOpt = Value; + } + + if (Arg *A = Args.getLastArg(OPT_analyzer_output)) { + llvm::StringRef Name = A->getValue(Args); + AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name) +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \ + .Case(CMDFLAG, PD_##NAME) +#include "clang/Frontend/Analyses.def" + .Default(NUM_ANALYSIS_DIAG_CLIENTS); + // FIXME: Error handling. + if (Value == NUM_ANALYSIS_DIAG_CLIENTS) + Diags.Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_O)->getAsString(Args) << Name; + else + Opts.AnalysisDiagOpt = Value; + } + + Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz); + Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph); + Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers); + Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress); + Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead); + Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume); + Opts.AnalyzeSpecificFunction = getLastArgValue(Args, OPT_analyze_function); + Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks); + Opts.EnableExperimentalInternalChecks = + Args.hasArg(OPT_analyzer_experimental_internal_checks); + Opts.TrimGraph = Args.hasArg(OPT_trim_egraph); +} + +static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, + Diagnostic &Diags) { + using namespace cc1options; + // -Os implies -O2 + if (Args.hasArg(OPT_Os)) + Opts.OptimizationLevel = 2; + else { + Opts.OptimizationLevel = getLastArgIntValue(Args, OPT_O, 0, Diags); + if (Opts.OptimizationLevel > 3) { + Diags.Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_O)->getAsString(Args) << Opts.OptimizationLevel; + Opts.OptimizationLevel = 3; + } + } + + // We must always run at least the always inlining pass. + Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining + : CodeGenOptions::OnlyAlwaysInlining; + + Opts.DebugInfo = Args.hasArg(OPT_g); + Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns); + Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); + Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); + Opts.NoCommon = Args.hasArg(OPT_fno_common); + Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float); + Opts.OptimizeSize = Args.hasArg(OPT_Os); + Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize); + + Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); + Opts.CodeModel = getLastArgValue(Args, OPT_mcode_model); + Opts.DebugPass = getLastArgValue(Args, OPT_mdebug_pass); + Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim); + Opts.FloatABI = getLastArgValue(Args, OPT_mfloat_abi); + Opts.LimitFloatPrecision = getLastArgValue(Args, OPT_mlimit_float_precision); + Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); + Opts.SoftFloat = Args.hasArg(OPT_msoft_float); + Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); + Opts.RelocationModel = getLastArgValue(Args, OPT_mrelocation_model, "pic"); + + Opts.MainFileName = getLastArgValue(Args, OPT_main_file_name); + + // FIXME: Put elsewhere? +#ifdef NDEBUG + Opts.VerifyModule = 0; +#else + Opts.VerifyModule = 1; +#endif +} + +static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, + ArgList &Args) { + using namespace cc1options; + Opts.OutputFile = getLastArgValue(Args, OPT_dependency_file); + Opts.Targets = getAllArgValues(Args, OPT_MT); + Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps); + Opts.UsePhonyTargets = Args.hasArg(OPT_MP); +} + +static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, + Diagnostic &Diags) { + using namespace cc1options; + Opts.IgnoreWarnings = Args.hasArg(OPT_w); + Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros); + Opts.Pedantic = Args.hasArg(OPT_pedantic); + Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors); + Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics); + Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics); + Opts.ShowColumn = !Args.hasArg(OPT_fno_show_column); + Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); + Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); + Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); + Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); + Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); + Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags); + Opts.DumpBuildInformation = getLastArgValue(Args, OPT_dump_build_information); + Opts.Warnings = getAllArgValues(Args, OPT_W); +} + +static FrontendOptions::InputKind +ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { + using namespace cc1options; + Opts.ProgramAction = frontend::ParseSyntaxOnly; + if (const Arg *A = Args.getLastArg(OPT_Action_Group)) { + switch (A->getOption().getID()) { + default: + assert(0 && "Invalid option in group!"); + case OPT_ast_dump: + Opts.ProgramAction = frontend::ASTDump; break; + case OPT_ast_print: + Opts.ProgramAction = frontend::ASTPrint; break; + case OPT_ast_print_xml: + Opts.ProgramAction = frontend::ASTPrintXML; break; + case OPT_ast_view: + Opts.ProgramAction = frontend::ASTView; break; + case OPT_dump_raw_tokens: + Opts.ProgramAction = frontend::DumpRawTokens; break; + case OPT_dump_record_layouts: + Opts.ProgramAction = frontend::DumpRecordLayouts; break; + case OPT_dump_tokens: + Opts.ProgramAction = frontend::DumpTokens; break; + case OPT_S: + Opts.ProgramAction = frontend::EmitAssembly; break; + case OPT_emit_llvm_bc: + Opts.ProgramAction = frontend::EmitBC; break; + case OPT_emit_html: + Opts.ProgramAction = frontend::EmitHTML; break; + case OPT_emit_llvm: + Opts.ProgramAction = frontend::EmitLLVM; break; + case OPT_emit_llvm_only: + Opts.ProgramAction = frontend::EmitLLVMOnly; break; + case OPT_fixit: + Opts.ProgramAction = frontend::FixIt; break; + case OPT_emit_pch: + Opts.ProgramAction = frontend::GeneratePCH; break; + case OPT_emit_pth: + Opts.ProgramAction = frontend::GeneratePTH; break; + case OPT_parse_noop: + Opts.ProgramAction = frontend::ParseNoop; break; + case OPT_parse_print_callbacks: + Opts.ProgramAction = frontend::ParsePrintCallbacks; break; + case OPT_fsyntax_only: + Opts.ProgramAction = frontend::ParseSyntaxOnly; break; + case OPT_print_decl_contexts: + Opts.ProgramAction = frontend::PrintDeclContext; break; + case OPT_E: + Opts.ProgramAction = frontend::PrintPreprocessedInput; break; + case OPT_rewrite_blocks: + Opts.ProgramAction = frontend::RewriteBlocks; break; + case OPT_rewrite_macros: + Opts.ProgramAction = frontend::RewriteMacros; break; + case OPT_rewrite_objc: + Opts.ProgramAction = frontend::RewriteObjC; break; + case OPT_rewrite_test: + Opts.ProgramAction = frontend::RewriteTest; break; + case OPT_analyze: + Opts.ProgramAction = frontend::RunAnalysis; break; + case OPT_Eonly: + Opts.ProgramAction = frontend::RunPreprocessorOnly; break; + } + } + if (const Arg *A = Args.getLastArg(OPT_plugin)) { + Opts.ProgramAction = frontend::PluginAction; + Opts.ActionName = A->getValue(Args); + } + + if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) { + Opts.CodeCompletionAt = + ParsedSourceLocation::FromString(A->getValue(Args)); + if (Opts.CodeCompletionAt.FileName.empty()) + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(Args); + } + Opts.DebugCodeCompletionPrinter = + !Args.hasArg(OPT_no_code_completion_debug_printer); + Opts.DisableFree = Args.hasArg(OPT_disable_free); + Opts.EmptyInputOnly = Args.hasArg(OPT_empty_input_only); + + Opts.FixItLocations.clear(); + for (arg_iterator it = Args.filtered_begin(OPT_fixit_at), + ie = Args.filtered_end(); it != ie; ++it) { + const char *Loc = it->getValue(Args); + ParsedSourceLocation PSL = ParsedSourceLocation::FromString(Loc); + + if (PSL.FileName.empty()) { + Diags.Report(diag::err_drv_invalid_value) << it->getAsString(Args) << Loc; + continue; + } + + Opts.FixItLocations.push_back(PSL); + } + + Opts.OutputFile = getLastArgValue(Args, OPT_o); + Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch); + Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros); + Opts.ShowStats = Args.hasArg(OPT_print_stats); + Opts.ShowTimers = Args.hasArg(OPT_ftime_report); + Opts.ViewClassInheritance = getLastArgValue(Args, OPT_cxx_inheritance_view); + + FrontendOptions::InputKind DashX = FrontendOptions::IK_None; + if (const Arg *A = Args.getLastArg(OPT_x)) { + DashX = llvm::StringSwitch<FrontendOptions::InputKind>(A->getValue(Args)) + .Case("c", FrontendOptions::IK_C) + .Case("cl", FrontendOptions::IK_OpenCL) + .Case("c", FrontendOptions::IK_C) + .Case("cl", FrontendOptions::IK_OpenCL) + .Case("c++", FrontendOptions::IK_CXX) + .Case("objective-c", FrontendOptions::IK_ObjC) + .Case("objective-c++", FrontendOptions::IK_ObjCXX) + .Case("cpp-output", FrontendOptions::IK_PreprocessedC) + .Case("assembler-with-cpp", FrontendOptions::IK_Asm) + .Case("c++-cpp-output", FrontendOptions::IK_PreprocessedCXX) + .Case("objective-c-cpp-output", FrontendOptions::IK_PreprocessedObjC) + .Case("objective-c++-cpp-output", FrontendOptions::IK_PreprocessedObjCXX) + .Case("c-header", FrontendOptions::IK_C) + .Case("objective-c-header", FrontendOptions::IK_ObjC) + .Case("c++-header", FrontendOptions::IK_CXX) + .Case("objective-c++-header", FrontendOptions::IK_ObjCXX) + .Case("ast", FrontendOptions::IK_AST) + .Default(FrontendOptions::IK_None); + if (DashX == FrontendOptions::IK_None) + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(Args); + } + + // '-' is the default input if none is given. + std::vector<std::string> Inputs = getAllArgValues(Args, OPT_INPUT); + Opts.Inputs.clear(); + if (Inputs.empty()) + Inputs.push_back("-"); + for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { + FrontendOptions::InputKind IK = DashX; + if (IK == FrontendOptions::IK_None) { + IK = FrontendOptions::getInputKindForExtension( + llvm::StringRef(Inputs[i]).rsplit('.').second); + // FIXME: Remove this hack. + if (i == 0) + DashX = IK; + } + Opts.Inputs.push_back(std::make_pair(IK, Inputs[i])); + } + + return DashX; +} + +static std::string GetBuiltinIncludePath(const char *Argv0, + void *MainAddr) { + llvm::sys::Path P = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr); + + if (!P.isEmpty()) { + P.eraseComponent(); // Remove /clang from foo/bin/clang + P.eraseComponent(); // Remove /bin from foo/bin + + // Get foo/lib/clang/<version>/include + P.appendComponent("lib"); + P.appendComponent("clang"); + P.appendComponent(CLANG_VERSION_STRING); + P.appendComponent("include"); + } + + return P.str(); +} + +static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, + const char *Argv0, void *MainAddr) { + using namespace cc1options; + Opts.Sysroot = getLastArgValue(Args, OPT_isysroot, "/"); + Opts.Verbose = Args.hasArg(OPT_v); + Opts.UseStandardIncludes = !Args.hasArg(OPT_nostdinc); + Opts.BuiltinIncludePath = ""; + // FIXME: Add an option for this, its a slow call. + if (!Args.hasArg(OPT_nobuiltininc)) + Opts.BuiltinIncludePath = GetBuiltinIncludePath(Argv0, MainAddr); + + // Add -I... and -F... options in order. + for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F), + ie = Args.filtered_end(); it != ie; ++it) + Opts.AddPath(it->getValue(Args), frontend::Angled, true, + /*IsFramework=*/ it->getOption().matches(OPT_F)); + + // Add -iprefix/-iwith-prefix/-iwithprefixbefore options. + llvm::StringRef Prefix = ""; // FIXME: This isn't the correct default prefix. + for (arg_iterator it = Args.filtered_begin(OPT_iprefix, OPT_iwithprefix, + OPT_iwithprefixbefore), + ie = Args.filtered_end(); it != ie; ++it) { + if (it->getOption().matches(OPT_iprefix)) + Prefix = it->getValue(Args); + else if (it->getOption().matches(OPT_iwithprefix)) + Opts.AddPath(Prefix.str() + it->getValue(Args), + frontend::System, false, false); + else + Opts.AddPath(Prefix.str() + it->getValue(Args), + frontend::Angled, false, false); + } + + for (arg_iterator it = Args.filtered_begin(OPT_idirafter), + ie = Args.filtered_end(); it != ie; ++it) + Opts.AddPath(it->getValue(Args), frontend::After, true, false); + for (arg_iterator it = Args.filtered_begin(OPT_iquote), + ie = Args.filtered_end(); it != ie; ++it) + Opts.AddPath(it->getValue(Args), frontend::Quoted, true, false); + for (arg_iterator it = Args.filtered_begin(OPT_isystem), + ie = Args.filtered_end(); it != ie; ++it) + Opts.AddPath(it->getValue(Args), frontend::System, true, false); + + // FIXME: Need options for the various environment variables! +} + +static void ParseLangArgs(LangOptions &Opts, ArgList &Args, + FrontendOptions::InputKind IK, + Diagnostic &Diags) { + // FIXME: Cleanup per-file based stuff. + + // Set some properties which depend soley on the input kind; it would be nice + // to move these to the language standard, and have the driver resolve the + // input kind + language standard. + if (IK == FrontendOptions::IK_Asm) { + Opts.AsmPreprocessor = 1; + } else if (IK == FrontendOptions::IK_ObjC || + IK == FrontendOptions::IK_ObjCXX || + IK == FrontendOptions::IK_PreprocessedObjC || + IK == FrontendOptions::IK_PreprocessedObjCXX) { + Opts.ObjC1 = Opts.ObjC2 = 1; + } + + LangStandard::Kind LangStd = LangStandard::lang_unspecified; + if (const Arg *A = Args.getLastArg(OPT_std_EQ)) { + LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue(Args)) +#define LANGSTANDARD(id, name, desc, features) \ + .Case(name, LangStandard::lang_##id) +#include "clang/Frontend/LangStandards.def" + .Default(LangStandard::lang_unspecified); + if (LangStd == LangStandard::lang_unspecified) + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(Args); + } + + if (LangStd == LangStandard::lang_unspecified) { + // Based on the base language, pick one. + switch (IK) { + case FrontendOptions::IK_None: + case FrontendOptions::IK_AST: + assert(0 && "Invalid input kind!"); + case FrontendOptions::IK_OpenCL: + LangStd = LangStandard::lang_opencl; + break; + case FrontendOptions::IK_Asm: + case FrontendOptions::IK_C: + case FrontendOptions::IK_PreprocessedC: + case FrontendOptions::IK_ObjC: + case FrontendOptions::IK_PreprocessedObjC: + LangStd = LangStandard::lang_gnu99; + break; + case FrontendOptions::IK_CXX: + case FrontendOptions::IK_PreprocessedCXX: + case FrontendOptions::IK_ObjCXX: + case FrontendOptions::IK_PreprocessedObjCXX: + LangStd = LangStandard::lang_gnucxx98; + break; + } + } + + const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); + Opts.BCPLComment = Std.hasBCPLComments(); + Opts.C99 = Std.isC99(); + Opts.CPlusPlus = Std.isCPlusPlus(); + Opts.CPlusPlus0x = Std.isCPlusPlus0x(); + Opts.Digraphs = Std.hasDigraphs(); + Opts.GNUMode = Std.isGNUMode(); + Opts.GNUInline = !Std.isC99(); + Opts.HexFloats = Std.hasHexFloats(); + Opts.ImplicitInt = Std.hasImplicitInt(); + + // OpenCL has some additional defaults. + if (LangStd == LangStandard::lang_opencl) { + Opts.OpenCL = 1; + Opts.AltiVec = 1; + Opts.CXXOperatorNames = 1; + Opts.LaxVectorConversions = 1; + } + + // OpenCL and C++ both have bool, true, false keywords. + Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; + + if (Opts.CPlusPlus) + Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); + + if (Args.hasArg(OPT_fobjc_gc_only)) + Opts.setGCMode(LangOptions::GCOnly); + else if (Args.hasArg(OPT_fobjc_gc)) + Opts.setGCMode(LangOptions::HybridGC); + + if (Args.hasArg(OPT_print_ivar_layout)) + Opts.ObjCGCBitmapPrint = 1; + + if (Args.hasArg(OPT_faltivec)) + Opts.AltiVec = 1; + + if (Args.hasArg(OPT_pthread)) + Opts.POSIXThreads = 1; + + llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility, + "default"); + if (Vis == "default") + Opts.setVisibilityMode(LangOptions::Default); + else if (Vis == "hidden") + Opts.setVisibilityMode(LangOptions::Hidden); + else if (Vis == "protected") + Opts.setVisibilityMode(LangOptions::Protected); + else + Diags.Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; + + Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); + + // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs + // is specified, or -std is set to a conforming mode. + Opts.Trigraphs = !Opts.GNUMode; + if (Args.hasArg(OPT_trigraphs)) + Opts.Trigraphs = 1; + + Opts.DollarIdents = !Opts.AsmPreprocessor; + if (Args.hasArg(OPT_fdollars_in_identifiers)) + Opts.DollarIdents = 1; + + Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); + Opts.Microsoft = Args.hasArg(OPT_fms_extensions); + Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); + if (Args.hasArg(OPT_fno_lax_vector_conversions)) + Opts.LaxVectorConversions = 0; + Opts.Exceptions = Args.hasArg(OPT_fexceptions); + Opts.Rtti = !Args.hasArg(OPT_fno_rtti); + Opts.Blocks = Args.hasArg(OPT_fblocks); + Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char); + Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); + Opts.Freestanding = Args.hasArg(OPT_ffreestanding); + Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; + Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); + Opts.AccessControl = Args.hasArg(OPT_faccess_control); + Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); + Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno); + Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99, + Diags); + Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); + Opts.ObjCConstantStringClass = getLastArgValue(Args, + OPT_fconstant_string_class); + Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); + Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); + Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); + Opts.Static = Args.hasArg(OPT_static_define); + Opts.OptimizeSize = 0; + + // FIXME: Eliminate this dependency. + unsigned Opt = + Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags); + Opts.Optimize = Opt != 0; + + // This is the __NO_INLINE__ define, which just depends on things like the + // optimization level and -fno-inline, not actually whether the backend has + // inlining enabled. + // + // FIXME: This is affected by other options (-fno-inline). + Opts.NoInline = !Opt; + + unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); + switch (SSP) { + default: + Diags.Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP; + break; + case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break; + case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break; + case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break; + } +} + +static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args) { + using namespace cc1options; + Opts.ImplicitPCHInclude = getLastArgValue(Args, OPT_include_pch); + Opts.ImplicitPTHInclude = getLastArgValue(Args, OPT_include_pth); + if (const Arg *A = Args.getLastArg(OPT_token_cache)) + Opts.TokenCache = A->getValue(Args); + else + Opts.TokenCache = Opts.ImplicitPTHInclude; + Opts.UsePredefines = !Args.hasArg(OPT_undef); + + // Add macros from the command line. + for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U), + ie = Args.filtered_end(); it != ie; ++it) { + if (it->getOption().matches(OPT_D)) + Opts.addMacroDef(it->getValue(Args)); + else + Opts.addMacroUndef(it->getValue(Args)); + } + + Opts.MacroIncludes = getAllArgValues(Args, OPT_imacros); + + // Add the ordered list of -includes. + for (arg_iterator it = Args.filtered_begin(OPT_include, OPT_include_pch, + OPT_include_pth), + ie = Args.filtered_end(); it != ie; ++it) { + // PCH is handled specially, we need to extra the original include path. + if (it->getOption().matches(OPT_include_pch)) { + std::string OriginalFile = + PCHReader::getOriginalSourceFile(it->getValue(Args)); + + // FIXME: Don't fail like this. + if (OriginalFile.empty()) + exit(1); + + Opts.Includes.push_back(OriginalFile); + } else + Opts.Includes.push_back(it->getValue(Args)); + } +} + +static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, + ArgList &Args) { + using namespace cc1options; + Opts.ShowCPP = !Args.hasArg(OPT_dM); + Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); + Opts.ShowLineMarkers = !Args.hasArg(OPT_P); + Opts.ShowComments = Args.hasArg(OPT_C); + Opts.ShowMacroComments = Args.hasArg(OPT_CC); +} + +static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { + using namespace cc1options; + Opts.ABI = getLastArgValue(Args, OPT_target_abi); + Opts.CPU = getLastArgValue(Args, OPT_mcpu); + Opts.Triple = getLastArgValue(Args, OPT_triple); + Opts.Features = getAllArgValues(Args, OPT_target_feature); + + // Use the host triple if unspecified. + if (Opts.Triple.empty()) + Opts.Triple = llvm::sys::getHostTriple(); +} + +// + +void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, + const char **ArgBegin, + const char **ArgEnd, + const char *Argv0, + void *MainAddr, + Diagnostic &Diags) { + // Parse the arguments. + llvm::OwningPtr<OptTable> Opts(createCC1OptTable()); + unsigned MissingArgIndex, MissingArgCount; + llvm::OwningPtr<InputArgList> Args( + Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount)); + + // Check for missing argument error. + if (MissingArgCount) + Diags.Report(diag::err_drv_missing_argument) + << Args->getArgString(MissingArgIndex) << MissingArgCount; + + // Issue errors on unknown arguments. + for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN), + ie = Args->filtered_end(); it != ie; ++it) + Diags.Report(diag::err_drv_unknown_argument) << it->getAsString(*Args); + + ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags); + ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, Diags); + ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args); + ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags); + FrontendOptions::InputKind DashX = + ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags); + ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args, + Argv0, MainAddr); + if (DashX != FrontendOptions::IK_AST) + ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags); + ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args); + ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args); + ParseTargetArgs(Res.getTargetOpts(), *Args); +} diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index c7f9359..478c339 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -21,14 +21,13 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/StringSet.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <string> using namespace clang; namespace { -class VISIBILITY_HIDDEN DependencyFileCallback : public PPCallbacks { +class DependencyFileCallback : public PPCallbacks { std::vector<std::string> Files; llvm::StringSet<> FilesSet; const Preprocessor *PP; diff --git a/lib/Frontend/DiagChecker.cpp b/lib/Frontend/DiagChecker.cpp index 26bb6cc..e7a66b1 100644 --- a/lib/Frontend/DiagChecker.cpp +++ b/lib/Frontend/DiagChecker.cpp @@ -149,7 +149,8 @@ static void FindExpectedDiags(Preprocessor &PP, 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()); + const llvm::MemoryBuffer *FromFile = PP.getSourceManager().getBuffer(FID); + Lexer RawLex(FID, FromFile, PP.getSourceManager(), PP.getLangOptions()); // Return comments as tokens, this is how we find expected diagnostics. RawLex.SetCommentRetentionState(true); diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index ff63a0d..91c946c 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -21,7 +21,7 @@ #include "llvm/Support/raw_ostream.h" using namespace clang; -FrontendAction::FrontendAction() : Instance(0), CurrentTimer(0) {} +FrontendAction::FrontendAction() : Instance(0) {} FrontendAction::~FrontendAction() {} @@ -144,8 +144,11 @@ void FrontendAction::Execute() { return; } - llvm::TimeRegion Timer(CurrentTimer); - ExecuteAction(); + if (CI.hasFrontendTimer()) { + llvm::TimeRegion Timer(CI.getFrontendTimer()); + ExecuteAction(); + } + else ExecuteAction(); } void FrontendAction::EndSourceFile() { diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 7a7537b..27e194e 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -170,7 +170,8 @@ ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, OS.reset(CI.createDefaultOutputFile(true, InFile, "bc")); return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(), - CI.getCodeGenOpts(), CI.getTargetOpts(), InFile, + CI.getCodeGenOpts(), CI.getTargetOpts(), + CI.getFrontendOpts().ShowTimers, InFile, OS.take(), CI.getLLVMContext()); } @@ -192,14 +193,15 @@ void DumpRawTokensAction::ExecuteAction() { SourceManager &SM = PP.getSourceManager(); // Start lexing the specified input file. - Lexer RawLex(SM.getMainFileID(), SM, PP.getLangOptions()); + const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); + Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions()); RawLex.SetKeepWhitespaceMode(true); Token RawTok; RawLex.LexFromRawLexer(RawTok); while (RawTok.isNot(tok::eof)) { PP.DumpToken(RawTok, true); - fprintf(stderr, "\n"); + llvm::errs() << "\n"; RawLex.LexFromRawLexer(RawTok); } } @@ -212,7 +214,7 @@ void DumpTokensAction::ExecuteAction() { do { PP.Lex(Tok); PP.DumpToken(Tok, true); - fprintf(stderr, "\n"); + llvm::errs() << "\n"; } while (Tok.isNot(tok::eof)); } @@ -222,8 +224,7 @@ void GeneratePTHAction::ExecuteAction() { CI.getFrontendOpts().OutputFile == "-") { // FIXME: Don't fail this way. // FIXME: Verify that we can actually seek in the given file. - llvm::errs() << "ERROR: PTH requires an seekable file for output!\n"; - ::exit(1); + llvm::llvm_report_error("PTH requires a seekable file for output!"); } llvm::raw_fd_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp index 0e4f83f..6251bac 100644 --- a/lib/Frontend/GeneratePCH.cpp +++ b/lib/Frontend/GeneratePCH.cpp @@ -20,16 +20,13 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Basic/FileManager.h" #include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/System/Path.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <string> using namespace clang; -using namespace llvm; namespace { - class VISIBILITY_HIDDEN PCHGenerator : public SemaConsumer { + class PCHGenerator : public SemaConsumer { const Preprocessor &PP; const char *isysroot; llvm::raw_ostream *Out; @@ -62,7 +59,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Write the PCH contents into a buffer std::vector<unsigned char> Buffer; - BitstreamWriter Stream(Buffer); + llvm::BitstreamWriter Stream(Buffer); PCHWriter Writer(Stream); // Emit the PCH file diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp index 3ba7abf..93421ca 100644 --- a/lib/Frontend/HTMLDiagnostics.cpp +++ b/lib/Frontend/HTMLDiagnostics.cpp @@ -21,7 +21,6 @@ #include "clang/Rewrite/HTMLRewrite.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" @@ -34,7 +33,7 @@ using namespace clang; namespace { -class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient { +class HTMLDiagnostics : public PathDiagnosticClient { llvm::sys::Path Directory, FilePrefix; bool createdDir, noDir; const Preprocessor &PP; diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index d19ae98..a40a569 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -170,9 +170,8 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base, const char *Dir32, const char *Dir64, const llvm::Triple &triple) { - // Add the common dirs + // Add the base dir AddPath(Base, System, true, false, false); - AddPath(Base + "/backward", System, true, false, false); // Add the multilib dirs llvm::Triple::ArchType arch = triple.getArch(); @@ -181,6 +180,9 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base, AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false); else AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false); + + // Add the backward dir + AddPath(Base + "/backward", System, true, false, false); } void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base, @@ -194,7 +196,15 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base, // FIXME: This probably should goto to some platform utils place. #ifdef _MSC_VER + // Read registry string. + // This also supports a means to look for high-versioned keys by use + // of a $VERSION placeholder in the key path. + // $VERSION in the key path is a placeholder for the version number, + // causing the highest value path to be searched for and used. + // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". + // There can be additional characters in the component. Only the numberic + // characters are compared. bool getSystemRegistryString(const char *keyPath, const char *valueName, char *value, size_t maxLength) { HKEY hRootKey = NULL; @@ -202,6 +212,7 @@ bool getSystemRegistryString(const char *keyPath, const char *valueName, const char* subKey = NULL; DWORD valueType; DWORD valueSize = maxLength - 1; + long lResult; bool returnValue = false; if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { hRootKey = HKEY_CLASSES_ROOT; @@ -221,13 +232,80 @@ bool getSystemRegistryString(const char *keyPath, const char *valueName, } 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); + const char *placeHolder = strstr(subKey, "$VERSION"); + char bestName[256]; + bestName[0] = '\0'; + // If we have a $VERSION placeholder, do the highest-version search. + if (placeHolder) { + const char *keyEnd = placeHolder - 1; + const char *nextKey = placeHolder; + // Find end of previous key. + while ((keyEnd > subKey) && (*keyEnd != '\\')) + keyEnd--; + // Find end of key containing $VERSION. + while (*nextKey && (*nextKey != '\\')) + nextKey++; + size_t partialKeyLength = keyEnd - subKey; + char partialKey[256]; + if (partialKeyLength > sizeof(partialKey)) + partialKeyLength = sizeof(partialKey); + strncpy(partialKey, subKey, partialKeyLength); + partialKey[partialKeyLength] = '\0'; + HKEY hTopKey = NULL; + lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey); + if (lResult == ERROR_SUCCESS) { + char keyName[256]; + int bestIndex = -1; + double bestValue = 0.0; + DWORD index, size = sizeof(keyName) - 1; + for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
+ NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
+ const char *sp = keyName;
+ while (*sp && !isdigit(*sp))
+ sp++;
+ if (!*sp)
+ continue;
+ const char *ep = sp + 1;
+ while (*ep && (isdigit(*ep) || (*ep == '.')))
+ ep++;
+ char numBuf[32];
+ strncpy(numBuf, sp, sizeof(numBuf) - 1);
+ numBuf[sizeof(numBuf) - 1] = '\0';
+ double value = strtod(numBuf, NULL);
+ if (value > bestValue) {
+ bestIndex = (int)index;
+ bestValue = value;
+ strcpy(bestName, keyName);
+ }
+ size = sizeof(keyName) - 1; + } + // If we found the highest versioned key, open the key and get the value. + if (bestIndex != -1) { + // Append rest of key. + strncat(bestName, nextKey, sizeof(bestName) - 1); + bestName[sizeof(bestName) - 1] = '\0'; + // Open the chosen key path remainder. + lResult = RegOpenKeyEx(hTopKey, bestName, 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); + } + } + RegCloseKey(hTopKey); + } + } + else { + 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); } @@ -240,35 +318,13 @@ bool getSystemRegistryString(const char *, const char *, char *, size_t) { // Get Visual Studio installation directory. bool getVisualStudioDir(std::string &path) { + char vsIDEInstallDir[256]; // 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); + bool hasVCDir = getSystemRegistryString( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", + "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 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) { + if (hasVCDir && vsIDEInstallDir[0]) { char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); if (p) *p = '\0'; @@ -307,6 +363,21 @@ bool getVisualStudioDir(std::string &path) { return(false); } + // Get Windows SDK installation directory. +bool getWindowsSDKDir(std::string &path) { + char windowsSDKInstallDir[256]; + // Try the Windows registry. + bool hasSDKDir = getSystemRegistryString( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", + "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1); + // If we have both vc80 and vc90, pick version we were compiled with. + if (hasSDKDir && windowsSDKInstallDir[0]) { + path = windowsSDKInstallDir; + return(true); + } + return(false); +} + void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) { // FIXME: temporary hack: hard-coded paths. llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS); @@ -324,10 +395,14 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) { case llvm::Triple::Win32: { std::string VSDir; + std::string WindowsSDKDir; if (getVisualStudioDir(VSDir)) { AddPath(VSDir + "\\VC\\include", System, false, false, false); - AddPath(VSDir + "\\VC\\PlatformSDK\\Include", - System, false, false, false); + if (getWindowsSDKDir(WindowsSDKDir)) + AddPath(WindowsSDKDir, System, false, false, false); + else + AddPath(VSDir + "\\VC\\PlatformSDK\\Include", + System, false, false, false); } else { // Default install paths. @@ -489,6 +564,9 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, const llvm::Triple &triple) { + if (Lang.CPlusPlus) + AddDefaultCPlusPlusIncludePaths(triple); + AddDefaultCIncludePaths(triple); // Add the default framework include paths on Darwin. @@ -496,9 +574,6 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, AddPath("/System/Library/Frameworks", System, true, false, true); AddPath("/Library/Frameworks", System, true, false, true); } - - if (Lang.CPlusPlus) - AddDefaultCPlusPlusIncludePaths(triple); } /// RemoveDuplicates - If there are duplicate directory entries in the specified diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index b77c240..972c21f 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -388,13 +388,20 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Buf); DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Buf); + DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Buf); + DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Buf); DefineTypeWidth("__INTMAX_WIDTH__", TI.getIntMaxType(), TI, Buf); DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(0), Buf); + DefineTypeWidth("__PTRDIFF_WIDTH__", TI.getPtrDiffType(0), TI, Buf); DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Buf); DefineTypeWidth("__INTPTR_WIDTH__", TI.getIntPtrType(), TI, Buf); DefineType("__SIZE_TYPE__", TI.getSizeType(), Buf); + DefineTypeWidth("__SIZE_WIDTH__", TI.getSizeType(), TI, Buf); DefineType("__WCHAR_TYPE__", TI.getWCharType(), Buf); + DefineTypeWidth("__WCHAR_WIDTH__", TI.getWCharType(), TI, Buf); DefineType("__WINT_TYPE__", TI.getWIntType(), Buf); + DefineTypeWidth("__WINT_WIDTH__", TI.getWIntType(), TI, Buf); + DefineTypeWidth("__SIG_ATOMIC_WIDTH__", TI.getSigAtomicType(), TI, Buf); DefineFloatMacros(Buf, "FLT", &TI.getFloatFormat()); DefineFloatMacros(Buf, "DBL", &TI.getDoubleFormat()); diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp new file mode 100644 index 0000000..771a58c --- /dev/null +++ b/lib/Frontend/LangStandards.cpp @@ -0,0 +1,44 @@ +//===--- LangStandards.cpp - Language Standard Definitions ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/LangStandard.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; +using namespace clang::frontend; + +#define LANGSTANDARD(id, name, desc, features) \ + static LangStandard Lang_##id = { name, desc, features }; +#include "clang/Frontend/LangStandards.def" + +const LangStandard &LangStandard::getLangStandardForKind(Kind K) { + switch (K) { + default: + llvm::llvm_unreachable("Invalid language kind!"); + case lang_unspecified: + llvm::llvm_report_error("getLangStandardForKind() on unspecified kind"); +#define LANGSTANDARD(id, name, desc, features) \ + case lang_##id: return Lang_##id; +#include "clang/Frontend/LangStandards.def" + } +} + +const LangStandard *LangStandard::getLangStandardForName(llvm::StringRef Name) { + Kind K = llvm::StringSwitch<Kind>(Name) +#define LANGSTANDARD(id, name, desc, features) \ + .Case(name, lang_##id) +#include "clang/Frontend/LangStandards.def" + .Default(lang_unspecified); + if (K == lang_unspecified) + return 0; + + return &getLangStandardForKind(K); +} + + diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index c9679b7..cb96bcb 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -31,7 +31,6 @@ #include "clang/Basic/Version.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/System/Path.h" @@ -357,7 +356,7 @@ Expr *PCHReader::ReadTypeExpr() { namespace { -class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait { +class PCHMethodPoolLookupTrait { PCHReader &Reader; public: @@ -465,7 +464,7 @@ typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait> PCHMethodPoolLookupTable; namespace { -class VISIBILITY_HIDDEN PCHIdentifierLookupTrait { +class PCHIdentifierLookupTrait { PCHReader &Reader; // If we know the IdentifierInfo in advance, it is here and we will @@ -676,7 +675,7 @@ bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) { namespace { -class VISIBILITY_HIDDEN PCHStatData { +class PCHStatData { public: const bool hasStat; const ino_t ino; @@ -692,7 +691,7 @@ public: : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {} }; -class VISIBILITY_HIDDEN PCHStatLookupTrait { +class PCHStatLookupTrait { public: typedef const char *external_key_type; typedef const char *internal_key_type; @@ -740,7 +739,7 @@ class VISIBILITY_HIDDEN PCHStatLookupTrait { /// /// This cache is very similar to the stat cache used by pretokenized /// headers. -class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache { +class PCHStatCache : public StatSysCallCache { typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy; CacheTy *Cache; @@ -1554,6 +1553,12 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { if (unsigned ObjCClassRedef = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); +#if 0 + // FIXME. Accommodate for this in several PCH/Index tests + if (unsigned ObjCSelRedef + = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) + Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); +#endif if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR]) Context->setBlockDescriptorType(GetType(String)); if (unsigned String @@ -2155,6 +2160,7 @@ QualType PCHReader::GetType(pch::TypeID ID) { 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; + case pch::PREDEF_TYPE_OBJC_SEL: T = Context->ObjCBuiltinSelTy; break; } assert(!T.isNull() && "Unknown predefined type"); @@ -2583,6 +2589,10 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { return Context->DeclarationNames.getCXXOperatorName( (OverloadedOperatorKind)Record[Idx++]); + case DeclarationName::CXXLiteralOperatorName: + return Context->DeclarationNames.getCXXLiteralOperatorName( + GetIdentifierInfo(Record, Idx)); + case DeclarationName::CXXUsingDirective: return DeclarationName::getUsingDirectiveName(); } diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 6a92a2d..03f3b4767 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -441,6 +441,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(AnalyzerNoReturn); STRING_ATTR(Annotate); STRING_ATTR(AsmLabel); + SIMPLE_ATTR(BaseCheck); case Attr::Blocks: New = ::new (*Context) BlocksAttr( @@ -461,6 +462,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(Deprecated); UNSIGNED_ATTR(Destructor); SIMPLE_ATTR(FastCall); + SIMPLE_ATTR(Final); case Attr::Format: { std::string Type = ReadString(Record, Idx); @@ -484,6 +486,7 @@ Attr *PCHReader::ReadAttributes() { } SIMPLE_ATTR(GNUInline); + SIMPLE_ATTR(Hiding); case Attr::IBOutletKind: New = ::new (*Context) IBOutletAttr(); @@ -517,6 +520,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(CFReturnsRetained); SIMPLE_ATTR(NSReturnsRetained); SIMPLE_ATTR(Overloadable); + SIMPLE_ATTR(Override); SIMPLE_ATTR(Packed); UNSIGNED_ATTR(PragmaPack); SIMPLE_ATTR(Pure); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 01af67d..00734a0 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -177,6 +177,7 @@ unsigned PCHStmtReader::VisitLabelStmt(LabelStmt *S) { unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) { VisitStmt(S); + S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3])); S->setThen(StmtStack[StmtStack.size() - 2]); S->setElse(StmtStack[StmtStack.size() - 1]); @@ -187,6 +188,7 @@ unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) { unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) { VisitStmt(S); + S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 2])); S->setBody(StmtStack.back()); S->setSwitchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -208,6 +210,7 @@ unsigned PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) { unsigned PCHStmtReader::VisitWhileStmt(WhileStmt *S) { VisitStmt(S); + S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); S->setCond(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2])); S->setBody(StmtStack.back()); S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -228,6 +231,7 @@ unsigned PCHStmtReader::VisitForStmt(ForStmt *S) { VisitStmt(S); S->setInit(StmtStack[StmtStack.size() - 4]); S->setCond(cast_or_null<Expr>(StmtStack[StmtStack.size() - 3])); + S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); S->setInc(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2])); S->setBody(StmtStack.back()); S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 8a45ebc..e79f9c9 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -33,7 +33,6 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitstreamWriter.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/Path.h" #include <cstdio> @@ -44,7 +43,7 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace { - class VISIBILITY_HIDDEN PCHTypeWriter { + class PCHTypeWriter { PCHWriter &Writer; PCHWriter::RecordData &Record; @@ -781,7 +780,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { namespace { // Trait used for the on-disk hash table of stat cache results. -class VISIBILITY_HIDDEN PCHStatCacheTrait { +class PCHStatCacheTrait { public: typedef const char * key_type; typedef key_type key_type_ref; @@ -1359,7 +1358,7 @@ uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context, namespace { // Trait used for the on-disk hash table used in the method pool. -class VISIBILITY_HIDDEN PCHMethodPoolTrait { +class PCHMethodPoolTrait { PCHWriter &Writer; public: @@ -1561,7 +1560,7 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { //===----------------------------------------------------------------------===// namespace { -class VISIBILITY_HIDDEN PCHIdentifierTableTrait { +class PCHIdentifierTableTrait { PCHWriter &Writer; Preprocessor &PP; @@ -1764,6 +1763,9 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record); break; + case Attr::BaseCheck: + break; + case Attr::Blocks: Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable break; @@ -1792,6 +1794,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { break; case Attr::FastCall: + case Attr::Final: break; case Attr::Format: { @@ -1816,6 +1819,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { } case Attr::GNUInline: + case Attr::Hiding: case Attr::IBOutletKind: case Attr::Malloc: case Attr::NoDebug: @@ -1836,6 +1840,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::CFReturnsRetained: case Attr::NSReturnsRetained: case Attr::Overloadable: + case Attr::Override: break; case Attr::PragmaPack: @@ -1989,6 +1994,10 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, AddTypeRef(Context.getsigjmp_bufType(), Record); AddTypeRef(Context.ObjCIdRedefinitionType, Record); AddTypeRef(Context.ObjCClassRedefinitionType, Record); +#if 0 + // FIXME. Accommodate for this in several PCH/Indexer tests + AddTypeRef(Context.ObjCSelRedefinitionType, Record); +#endif AddTypeRef(Context.getRawBlockdescriptorType(), Record); AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record); Stream.EmitRecord(pch::SPECIAL_TYPES, Record); @@ -2204,6 +2213,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { 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::ObjCSel: ID = pch::PREDEF_TYPE_OBJC_SEL; break; case BuiltinType::UndeducedAuto: assert(0 && "Should not see undeduced auto here"); break; @@ -2274,6 +2284,10 @@ void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) { Record.push_back(Name.getCXXOverloadedOperator()); break; + case DeclarationName::CXXLiteralOperatorName: + AddIdentifierRef(Name.getCXXLiteralIdentifier(), Record); + break; + case DeclarationName::CXXUsingDirective: // No extra data to emit break; diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 78a56db..27b83ed 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -170,6 +170,7 @@ void PCHStmtWriter::VisitLabelStmt(LabelStmt *S) { void PCHStmtWriter::VisitIfStmt(IfStmt *S) { VisitStmt(S); + Writer.AddDeclRef(S->getConditionVariable(), Record); Writer.WriteSubStmt(S->getCond()); Writer.WriteSubStmt(S->getThen()); Writer.WriteSubStmt(S->getElse()); @@ -180,6 +181,7 @@ void PCHStmtWriter::VisitIfStmt(IfStmt *S) { void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) { VisitStmt(S); + Writer.AddDeclRef(S->getConditionVariable(), Record); Writer.WriteSubStmt(S->getCond()); Writer.WriteSubStmt(S->getBody()); Writer.AddSourceLocation(S->getSwitchLoc(), Record); @@ -191,6 +193,7 @@ void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) { void PCHStmtWriter::VisitWhileStmt(WhileStmt *S) { VisitStmt(S); + Writer.AddDeclRef(S->getConditionVariable(), Record); Writer.WriteSubStmt(S->getCond()); Writer.WriteSubStmt(S->getBody()); Writer.AddSourceLocation(S->getWhileLoc(), Record); @@ -211,6 +214,7 @@ void PCHStmtWriter::VisitForStmt(ForStmt *S) { VisitStmt(S); Writer.WriteSubStmt(S->getInit()); Writer.WriteSubStmt(S->getCond()); + Writer.AddDeclRef(S->getConditionVariable(), Record); Writer.WriteSubStmt(S->getInc()); Writer.WriteSubStmt(S->getBody()); Writer.AddSourceLocation(S->getForLoc(), Record); diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp index 6bcf39a..80ee2c2 100644 --- a/lib/Frontend/PlistDiagnostics.cpp +++ b/lib/Frontend/PlistDiagnostics.cpp @@ -16,10 +16,8 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Casting.h" -#include "llvm/System/Path.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" using namespace clang; @@ -32,7 +30,7 @@ namespace clang { } namespace { - class VISIBILITY_HIDDEN PlistDiagnostics : public PathDiagnosticClient { + class PlistDiagnostics : public PathDiagnosticClient { std::vector<const PathDiagnostic*> BatchedDiags; const std::string OutputFile; const LangOptions &LangOpts; diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index deb5498..c5dc979 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -305,14 +305,16 @@ namespace { } virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, StmtArg ThenVal, + FullExprArg CondVal, DeclPtrTy CondVar, + StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } - virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) { + virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, + DeclPtrTy CondVar) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } @@ -325,7 +327,8 @@ namespace { } virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, StmtArg Body) { + FullExprArg Cond, DeclPtrTy CondVar, + StmtArg Body) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } @@ -338,8 +341,10 @@ namespace { } virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - ExprArg Third, SourceLocation RParenLoc, + StmtArg First, FullExprArg Second, + DeclPtrTy SecondVar, + FullExprArg Third, + SourceLocation RParenLoc, StmtArg Body) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp index b5d59c0..0bcbd4f 100644 --- a/lib/Frontend/RewriteMacros.cpp +++ b/lib/Frontend/RewriteMacros.cpp @@ -65,7 +65,8 @@ static void LexRawTokensFromMainFile(Preprocessor &PP, // 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()); + const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); + Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions()); // Switch on comment lexing because we really do want them. RawLex.SetCommentRetentionState(true); diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index 06955e5..710fa55 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -2627,7 +2627,7 @@ 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*/, 0, VarDecl::Extern); + ID, getProtocolType(), 0, VarDecl::Extern); DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation()); Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, Context->getPointerType(DRE->getType()), diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index 4a3c0bf..c0977b5 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -17,7 +17,6 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" #include "clang/Basic/SourceManager.h" -#include "llvm/Support/Compiler.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -25,7 +24,7 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace { - class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> { + class StmtXML : public StmtVisitor<StmtXML> { DocumentXML& Doc; //static const char *getOpcodeStr(UnaryOperator::Opcode Op); @@ -61,8 +60,6 @@ namespace { Doc.PrintDecl(*DI); } } 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) DumpSubTree(*i); diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp index 34bc3c7..fdf2ec8 100644 --- a/lib/Frontend/TextDiagnosticBuffer.cpp +++ b/lib/Frontend/TextDiagnosticBuffer.cpp @@ -20,20 +20,29 @@ using namespace clang; /// void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info) { - llvm::SmallString<100> StrC; - Info.FormatDiagnostic(StrC); - std::string Str(StrC.begin(), StrC.end()); + llvm::SmallString<100> Buf; + Info.FormatDiagnostic(Buf); switch (Level) { default: assert(0 && "Diagnostic not handled during diagnostic buffering!"); case Diagnostic::Note: - Notes.push_back(std::make_pair(Info.getLocation(), Str)); + Notes.push_back(std::make_pair(Info.getLocation(), Buf.str())); break; case Diagnostic::Warning: - Warnings.push_back(std::make_pair(Info.getLocation(), Str)); + Warnings.push_back(std::make_pair(Info.getLocation(), Buf.str())); break; case Diagnostic::Error: case Diagnostic::Fatal: - Errors.push_back(std::make_pair(Info.getLocation(), Str)); + Errors.push_back(std::make_pair(Info.getLocation(), Buf.str())); break; } } + +void TextDiagnosticBuffer::FlushDiagnostics(Diagnostic &Diags) const { + // FIXME: Flush the diagnostics in order. + for (const_iterator it = err_begin(), ie = err_end(); it != ie; ++it) + Diags.Report(Diags.getCustomDiagID(Diagnostic::Error, it->second.c_str())); + for (const_iterator it = warn_begin(), ie = warn_end(); it != ie; ++it) + Diags.Report(Diags.getCustomDiagID(Diagnostic::Warning,it->second.c_str())); + for (const_iterator it = note_begin(), ie = note_end(); it != ie; ++it) + Diags.Report(Diags.getCustomDiagID(Diagnostic::Note, it->second.c_str())); +} diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp index 2891aec..99ec910 100644 --- a/lib/Frontend/VerifyDiagnosticsClient.cpp +++ b/lib/Frontend/VerifyDiagnosticsClient.cpp @@ -164,12 +164,14 @@ static void FindExpectedDiags(Preprocessor &PP, DiagList &ExpectedNotes) { // 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(); - if (PP.getSourceManager().getMainFileID().isInvalid()) + SourceManager &SM = PP.getSourceManager(); + FileID FID = SM.getMainFileID(); + if (SM.getMainFileID().isInvalid()) return; // Create a lexer to lex all the tokens of the main file in raw mode. - Lexer RawLex(FID, PP.getSourceManager(), PP.getLangOptions()); + const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID); + Lexer RawLex(FID, FromFile, SM, PP.getLangOptions()); // Return comments as tokens, this is how we find expected diagnostics. RawLex.SetCommentRetentionState(true); |