diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTConsumers.cpp | 13 | ||||
-rw-r--r-- | lib/Frontend/AnalysisConsumer.cpp | 12 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 93 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 17 | ||||
-rw-r--r-- | lib/Frontend/FixItRewriter.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 6 | ||||
-rw-r--r-- | lib/Frontend/InitPreprocessor.cpp | 442 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 71 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderStmt.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 16 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterStmt.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/PrintParserCallbacks.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/RewriteObjC.cpp | 314 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticPrinter.cpp | 9 |
17 files changed, 674 insertions, 345 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index f1a6666..52b597e 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -408,6 +408,19 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "<function template> " << FTD->getNameAsString() << "\n"; break; } + case Decl::FileScopeAsm: { + Out << "<file-scope asm>\n"; + break; + } + case Decl::UsingDirective: { + Out << "<using directive>\n"; + break; + } + case Decl::NamespaceAlias: { + NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I); + Out << "<namespace alias> " << NAD->getNameAsString() << "\n"; + break; + } default: Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n"; assert(0 && "decl unhandled"); diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index 6824d8f..ad152d3 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -363,7 +363,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, if (!mgr.getLiveVariables(D)) return; - GRExprEngine Eng(mgr); + GRExprEngine Eng(mgr, TF.take()); if (C.Opts.EnableExperimentalInternalChecks) RegisterExperimentalInternalChecks(Eng); @@ -373,8 +373,6 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, if (C.Opts.EnableExperimentalChecks) RegisterExperimentalChecks(Eng); - Eng.setTransferFunctionsAndCheckers(tf); - // Set the graph auditor. llvm::OwningPtr<ExplodedNode::Auditor> Auditor; if (mgr.shouldVisualizeUbigraph()) { @@ -494,7 +492,9 @@ static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr, // Display progress. C.DisplayFunction(D); - GRExprEngine Eng(mgr); + // FIXME: Make a fake transfer function. The GRTransferFunc interface + // eventually will be removed. + GRExprEngine Eng(mgr, new GRTransferFuncs()); if (C.Opts.EnableExperimentalInternalChecks) RegisterExperimentalInternalChecks(Eng); @@ -503,10 +503,6 @@ static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr, if (C.Opts.EnableExperimentalChecks) RegisterExperimentalChecks(Eng); - - // Make a fake transfer function. The GRTransferFunc interface will be - // removed. - Eng.setTransferFunctionsAndCheckers(new GRTransferFuncs()); // Register call inliner as the last checker. RegisterCallInliner(Eng); diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 2a6a8a8..19c740d 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -14,10 +14,12 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Version.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PTHManager.h" #include "clang/Frontend/ChainedDiagnosticClient.h" +#include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/PCHReader.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" @@ -28,6 +30,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Timer.h" +#include "llvm/System/Host.h" #include "llvm/System/Path.h" #include "llvm/System/Program.h" using namespace clang; @@ -155,7 +158,8 @@ void CompilerInstance::createPreprocessor() { PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), getPreprocessorOpts(), getHeaderSearchOpts(), getDependencyOutputOpts(), getTarget(), - getSourceManager(), getFileManager())); + getFrontendOpts(), getSourceManager(), + getFileManager())); } Preprocessor * @@ -165,6 +169,7 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, const HeaderSearchOptions &HSOpts, const DependencyOutputOptions &DepOpts, const TargetInfo &Target, + const FrontendOptions &FEOpts, SourceManager &SourceMgr, FileManager &FileMgr) { // Create a PTH manager if we are using some form of a token cache. @@ -186,7 +191,7 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, PP->setPTHManager(PTHMgr); } - InitializePreprocessor(*PP, PPOpts, HSOpts); + InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts); // Handle generating dependencies, if requested. if (!DepOpts.OutputFile.empty()) @@ -409,3 +414,87 @@ bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile, return true; } + +// High-Level Operations + +bool CompilerInstance::ExecuteAction(FrontendAction &Act) { + assert(hasDiagnostics() && "Diagnostics engine is not initialized!"); + assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!"); + assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!"); + + // FIXME: Take this as an argument, once all the APIs we used have moved to + // taking it as an input instead of hard-coding llvm::errs. + llvm::raw_ostream &OS = llvm::errs(); + + // Create the target instance. + setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts())); + if (!hasTarget()) + return false; + + // 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. + getTarget().setForcedLangOptions(getLangOpts()); + + // Validate/process some options. + if (getHeaderSearchOpts().Verbose) + OS << "clang -cc1 version " CLANG_VERSION_STRING + << " based upon " << PACKAGE_STRING + << " hosted on " << llvm::sys::getHostTriple() << "\n"; + + if (getFrontendOpts().ShowTimers) + createFrontendTimer(); + + for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) { + const std::string &InFile = getFrontendOpts().Inputs[i].second; + + // If we aren't using an AST file, setup the file and source managers and + // the preprocessor. + bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST; + if (!IsAST) { + if (!i) { + // Create a file manager object to provide access to and cache the + // filesystem. + createFileManager(); + + // Create the source manager. + createSourceManager(); + } else { + // Reset the ID tables if we are reusing the SourceManager. + getSourceManager().clearIDTables(); + } + + // Create the preprocessor. + createPreprocessor(); + } + + if (Act.BeginSourceFile(*this, InFile, IsAST)) { + Act.Execute(); + Act.EndSourceFile(); + } + } + + if (getDiagnosticOpts().ShowCarets) + if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics()) + OS << NumDiagnostics << " diagnostic" + << (NumDiagnostics == 1 ? "" : "s") + << " generated.\n"; + + if (getFrontendOpts().ShowStats) { + getFileManager().PrintStats(); + OS << "\n"; + } + + // Return the appropriate status when verifying diagnostics. + // + // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need + // this. + if (getDiagnosticOpts().VerifyDiagnostics) + return !static_cast<VerifyDiagnosticsClient&>( + getDiagnosticClient()).HadErrors(); + + return !getDiagnostics().getNumErrors(); +} + + diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 63f66fa..0bca475 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -222,6 +222,10 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, Res.push_back("-verify"); if (Opts.ShowOptionNames) Res.push_back("-fdiagnostics-show-option"); + if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) { + Res.push_back("-ftabstop"); + Res.push_back(llvm::utostr(Opts.TabStop)); + } if (Opts.MessageLength) { Res.push_back("-fmessage-length"); Res.push_back(llvm::utostr(Opts.MessageLength)); @@ -479,8 +483,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fblocks"); if (Opts.EmitAllDecls) Res.push_back("-femit-all-decls"); - if (!Opts.MathErrno) - Res.push_back("-fno-math-errno"); + if (Opts.MathErrno) + Res.push_back("-fmath-errno"); if (Opts.OverflowChecking) Res.push_back("-ftrapv"); if (Opts.HeinousExtensions) @@ -804,6 +808,13 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); + Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, + DiagnosticOptions::DefaultTabStop, Diags); + if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { + Diags.Report(diag::warn_ignoring_ftabstop_value) + << Opts.TabStop << DiagnosticOptions::DefaultTabStop; + Opts.TabStop = DiagnosticOptions::DefaultTabStop; + } Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags); Opts.DumpBuildInformation = getLastArgValue(Args, OPT_dump_build_information); Opts.Warnings = getAllArgValues(Args, OPT_W); @@ -1147,7 +1158,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, 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.MathErrno = Args.hasArg(OPT_fmath_errno); Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99, Diags); Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); diff --git a/lib/Frontend/FixItRewriter.cpp b/lib/Frontend/FixItRewriter.cpp index 4fa2b3c..0b04cf2 100644 --- a/lib/Frontend/FixItRewriter.cpp +++ b/lib/Frontend/FixItRewriter.cpp @@ -115,6 +115,9 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel, if (!AcceptableLocation) return; + } else if (DiagLevel == Diagnostic::Note) { + // Don't apply fix-it modifications in notes. + return; } // Make sure that we can perform all of the modifications we diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 4c647fda..0baba3f 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -280,7 +280,9 @@ void PrintParseAction::ExecuteAction() { void PrintPreprocessedAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); - llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); + // Output file needs to be set to 'Binary', to avoid converting Unix style + // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). + llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); if (!OS) return; DoPrintPreprocessedInput(CI.getPreprocessor(), OS, diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 9555125..6fceb98 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -477,6 +477,9 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", "i686-apple-darwin8", "", "", triple); break; + case llvm::Triple::DragonFly: + AddPath("/usr/include/c++/4.1", System, true, false, false); + break; case llvm::Triple::Linux: // Exherbo (2009-10-26) AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", @@ -553,9 +556,6 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl "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: diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index c1fc92d..e4c380a 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -14,13 +14,12 @@ #include "clang/Frontend/Utils.h" #include "clang/Basic/TargetInfo.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/PreprocessorOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APFloat.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/Path.h" using namespace clang; @@ -28,43 +27,22 @@ using namespace clang; // Append a #define line to Buf for Macro. Macro should be of the form XXX, // in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit // "#define XXX Y z W". To get a #define with no value, use "XXX=". -static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro, - Diagnostic *Diags = 0) { - const char *Command = "#define "; - Buf.insert(Buf.end(), Command, Command+strlen(Command)); - if (const char *Equal = strchr(Macro, '=')) { - // Turn the = into ' '. - Buf.insert(Buf.end(), Macro, Equal); - Buf.push_back(' '); - +static void DefineBuiltinMacro(MacroBuilder &Builder, llvm::StringRef Macro, + Diagnostic &Diags) { + std::pair<llvm::StringRef, llvm::StringRef> MacroPair = Macro.split('='); + llvm::StringRef MacroName = MacroPair.first; + llvm::StringRef MacroBody = MacroPair.second; + if (MacroName.size() != Macro.size()) { // Per GCC -D semantics, the macro ends at \n if it exists. - const char *End = strpbrk(Equal, "\n\r"); - if (End) { - assert(Diags && "Unexpected macro with embedded newline!"); - Diags->Report(diag::warn_fe_macro_contains_embedded_newline) - << std::string(Macro, Equal); - } else { - End = Equal+strlen(Equal); - } - - Buf.insert(Buf.end(), Equal+1, End); + llvm::StringRef::size_type End = MacroBody.find_first_of("\n\r"); + if (End != llvm::StringRef::npos) + Diags.Report(diag::warn_fe_macro_contains_embedded_newline) + << MacroName; + Builder.defineMacro(MacroName, MacroBody.substr(0, End)); } else { // Push "macroname 1". - Buf.insert(Buf.end(), Macro, Macro+strlen(Macro)); - Buf.push_back(' '); - Buf.push_back('1'); + Builder.defineMacro(Macro); } - Buf.push_back('\n'); -} - -// Append a #undef line to Buf for Macro. Macro should be of the form XXX -// and we emit "#undef XXX". -static void UndefineBuiltinMacro(std::vector<char> &Buf, const char *Macro) { - // Push "macroname". - const char *Command = "#undef "; - Buf.insert(Buf.end(), Command, Command+strlen(Command)); - Buf.insert(Buf.end(), Macro, Macro+strlen(Macro)); - Buf.push_back('\n'); } std::string clang::NormalizeDashIncludePath(llvm::StringRef File) { @@ -83,42 +61,25 @@ std::string clang::NormalizeDashIncludePath(llvm::StringRef File) { return Lexer::Stringify(Path.str()); } -/// Add the quoted name of an implicit include file. -static void AddQuotedIncludePath(std::vector<char> &Buf, - const std::string &File) { - - // Escape double quotes etc. - Buf.push_back('"'); - std::string EscapedFile = NormalizeDashIncludePath(File); - 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, - const std::string &File) { - const char *Inc = "#include "; - Buf.insert(Buf.end(), Inc, Inc+strlen(Inc)); - AddQuotedIncludePath(Buf, File); - Buf.push_back('\n'); +static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File) { + Builder.append("#include \"" + + llvm::Twine(NormalizeDashIncludePath(File)) + "\""); } -static void AddImplicitIncludeMacros(std::vector<char> &Buf, - const std::string &File) { - const char *Inc = "#__include_macros "; - Buf.insert(Buf.end(), Inc, Inc+strlen(Inc)); - AddQuotedIncludePath(Buf, File); - Buf.push_back('\n'); +static void AddImplicitIncludeMacros(MacroBuilder &Builder, + llvm::StringRef File) { + Builder.append("#__include_macros \"" + + llvm::Twine(NormalizeDashIncludePath(File)) + "\""); // Marker token to stop the __include_macros fetch loop. - const char *Marker = "##\n"; // ##? - Buf.insert(Buf.end(), Marker, Marker+strlen(Marker)); + Builder.append("##"); // ##? } /// AddImplicitIncludePTH - Add an implicit #include using the original file /// used to generate a PTH cache. -static void AddImplicitIncludePTH(std::vector<char> &Buf, Preprocessor &PP, - const std::string& ImplicitIncludePTH) { +static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP, + llvm::StringRef ImplicitIncludePTH) { PTHManager *P = PP.getPTHManager(); assert(P && "No PTHManager."); const char *OriginalFile = P->getOriginalSourceFile(); @@ -129,7 +90,7 @@ static void AddImplicitIncludePTH(std::vector<char> &Buf, Preprocessor &PP, return; } - AddImplicitInclude(Buf, OriginalFile); + AddImplicitInclude(Builder, OriginalFile); } /// PickFP - This is used to pick a value based on the FP semantics of the @@ -150,7 +111,7 @@ static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal, return IEEEQuadVal; } -static void DefineFloatMacros(std::vector<char> &Buf, const char *Prefix, +static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix, const llvm::fltSemantics *Sem) { const char *DenormMin, *Epsilon, *Max, *Min; DenormMin = PickFP(Sem, "1.40129846e-45F", "4.9406564584124654e-324", @@ -162,7 +123,6 @@ static void DefineFloatMacros(std::vector<char> &Buf, const char *Prefix, "1.08420217248550443401e-19L", "4.94065645841246544176568792868221e-324L", "1.92592994438723585305597794258492732e-34L"); - int HasInifinity = 1, HasQuietNaN = 1; int MantissaDigits = PickFP(Sem, 24, 53, 64, 106, 113); int Min10Exp = PickFP(Sem, -37, -307, -4931, -291, -4931); int Max10Exp = PickFP(Sem, 38, 308, 4932, 308, 4932); @@ -177,312 +137,281 @@ static void DefineFloatMacros(std::vector<char> &Buf, const char *Prefix, "1.79769313486231580793728971405301e+308L", "1.18973149535723176508575932662800702e+4932L"); - char MacroBuf[100]; - sprintf(MacroBuf, "__%s_DENORM_MIN__=%s", Prefix, DenormMin); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_DIG__=%d", Prefix, Digits); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_EPSILON__=%s", Prefix, Epsilon); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_HAS_INFINITY__=%d", Prefix, HasInifinity); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_HAS_QUIET_NAN__=%d", Prefix, HasQuietNaN); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_MANT_DIG__=%d", Prefix, MantissaDigits); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_MAX_10_EXP__=%d", Prefix, Max10Exp); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_MAX_EXP__=%d", Prefix, MaxExp); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_MAX__=%s", Prefix, Max); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_MIN_10_EXP__=(%d)", Prefix, Min10Exp); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_MIN_EXP__=(%d)", Prefix, MinExp); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_MIN__=%s", Prefix, Min); - DefineBuiltinMacro(Buf, MacroBuf); - sprintf(MacroBuf, "__%s_HAS_DENORM__=1", Prefix); - DefineBuiltinMacro(Buf, MacroBuf); + llvm::Twine DefPrefix = "__" + Prefix + "_"; + + Builder.defineMacro(DefPrefix + "DENORM_MIN__", DenormMin); + Builder.defineMacro(DefPrefix + "HAS_DENORM__"); + Builder.defineMacro(DefPrefix + "DIG__", llvm::Twine(Digits)); + Builder.defineMacro(DefPrefix + "EPSILON__", llvm::Twine(Epsilon)); + Builder.defineMacro(DefPrefix + "HAS_INFINITY__"); + Builder.defineMacro(DefPrefix + "HAS_QUIET_NAN__"); + Builder.defineMacro(DefPrefix + "MANT_DIG__", llvm::Twine(MantissaDigits)); + + Builder.defineMacro(DefPrefix + "MAX_10_EXP__", llvm::Twine(Max10Exp)); + Builder.defineMacro(DefPrefix + "MAX_EXP__", llvm::Twine(MaxExp)); + Builder.defineMacro(DefPrefix + "MAX__", llvm::Twine(Max)); + + Builder.defineMacro(DefPrefix + "MIN_10_EXP__","("+llvm::Twine(Min10Exp)+")"); + Builder.defineMacro(DefPrefix + "MIN_EXP__", "("+llvm::Twine(MinExp)+")"); + Builder.defineMacro(DefPrefix + "MIN__", llvm::Twine(Min)); } /// DefineTypeSize - Emit a macro to the predefines buffer that declares a macro /// named MacroName with the max value for a type with width 'TypeWidth' a /// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL). -static void DefineTypeSize(const char *MacroName, unsigned TypeWidth, - const char *ValSuffix, bool isSigned, - std::vector<char> &Buf) { - char MacroBuf[60]; +static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth, + llvm::StringRef ValSuffix, bool isSigned, + MacroBuilder& Builder) { long long MaxVal; if (isSigned) MaxVal = (1LL << (TypeWidth - 1)) - 1; else MaxVal = ~0LL >> (64-TypeWidth); - // FIXME: Switch to using raw_ostream and avoid utostr(). - sprintf(MacroBuf, "%s=%s%s", MacroName, llvm::utostr(MaxVal).c_str(), - ValSuffix); - DefineBuiltinMacro(Buf, MacroBuf); + Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix); } /// DefineTypeSize - An overloaded helper that uses TargetInfo to determine /// the width, suffix, and signedness of the given type -static void DefineTypeSize(const char *MacroName, TargetInfo::IntType Ty, - const TargetInfo &TI, std::vector<char> &Buf) { +static void DefineTypeSize(llvm::StringRef MacroName, TargetInfo::IntType Ty, + const TargetInfo &TI, MacroBuilder &Builder) { DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty), - TI.isTypeSigned(Ty), Buf); + TI.isTypeSigned(Ty), Builder); } -static void DefineType(const char *MacroName, TargetInfo::IntType Ty, - std::vector<char> &Buf) { - char MacroBuf[60]; - sprintf(MacroBuf, "%s=%s", MacroName, TargetInfo::getTypeName(Ty)); - DefineBuiltinMacro(Buf, MacroBuf); +static void DefineType(const llvm::Twine &MacroName, TargetInfo::IntType Ty, + MacroBuilder &Builder) { + Builder.defineMacro(MacroName, TargetInfo::getTypeName(Ty)); } -static void DefineTypeWidth(const char *MacroName, TargetInfo::IntType Ty, - const TargetInfo &TI, std::vector<char> &Buf) { - char MacroBuf[60]; - sprintf(MacroBuf, "%s=%d", MacroName, TI.getTypeWidth(Ty)); - DefineBuiltinMacro(Buf, MacroBuf); +static void DefineTypeWidth(llvm::StringRef MacroName, TargetInfo::IntType Ty, + const TargetInfo &TI, MacroBuilder &Builder) { + Builder.defineMacro(MacroName, llvm::Twine(TI.getTypeWidth(Ty))); } static void DefineExactWidthIntType(TargetInfo::IntType Ty, - const TargetInfo &TI, std::vector<char> &Buf) { - char MacroBuf[60]; + const TargetInfo &TI, MacroBuilder &Builder) { int TypeWidth = TI.getTypeWidth(Ty); - sprintf(MacroBuf, "__INT%d_TYPE__", TypeWidth); - DefineType(MacroBuf, Ty, Buf); + DefineType("__INT" + llvm::Twine(TypeWidth) + "_TYPE__", Ty, Builder); - - const char *ConstSuffix = TargetInfo::getTypeConstantSuffix(Ty); - if (strlen(ConstSuffix) > 0) { - sprintf(MacroBuf, "__INT%d_C_SUFFIX__=%s", TypeWidth, ConstSuffix); - DefineBuiltinMacro(Buf, MacroBuf); - } + llvm::StringRef ConstSuffix(TargetInfo::getTypeConstantSuffix(Ty)); + if (!ConstSuffix.empty()) + Builder.defineMacro("__INT" + llvm::Twine(TypeWidth) + "_C_SUFFIX__", + ConstSuffix); } static void InitializePredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, - std::vector<char> &Buf) { - char MacroBuf[60]; + const FrontendOptions &FEOpts, + MacroBuilder &Builder) { // Compiler version introspection macros. - DefineBuiltinMacro(Buf, "__llvm__=1"); // LLVM Backend - DefineBuiltinMacro(Buf, "__clang__=1"); // Clang Frontend + Builder.defineMacro("__llvm__"); // LLVM Backend + Builder.defineMacro("__clang__"); // 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\""); - + Builder.defineMacro("__GNUC_MINOR__", "2"); + Builder.defineMacro("__GNUC_PATCHLEVEL__", "1"); + Builder.defineMacro("__GNUC__", "4"); + Builder.defineMacro("__GXX_ABI_VERSION", "1002"); + Builder.defineMacro("__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"); + Builder.defineMacro("__STDC__"); if (LangOpts.AsmPreprocessor) - DefineBuiltinMacro(Buf, "__ASSEMBLER__=1"); + Builder.defineMacro("__ASSEMBLER__"); if (!LangOpts.CPlusPlus) { if (LangOpts.C99) - DefineBuiltinMacro(Buf, "__STDC_VERSION__=199901L"); + Builder.defineMacro("__STDC_VERSION__", "199901L"); else if (!LangOpts.GNUMode && LangOpts.Digraphs) - DefineBuiltinMacro(Buf, "__STDC_VERSION__=199409L"); + Builder.defineMacro("__STDC_VERSION__", "199409L"); } // Standard conforming mode? if (!LangOpts.GNUMode) - DefineBuiltinMacro(Buf, "__STRICT_ANSI__=1"); + Builder.defineMacro("__STRICT_ANSI__"); if (LangOpts.CPlusPlus0x) - DefineBuiltinMacro(Buf, "__GXX_EXPERIMENTAL_CXX0X__"); + Builder.defineMacro("__GXX_EXPERIMENTAL_CXX0X__"); if (LangOpts.Freestanding) - DefineBuiltinMacro(Buf, "__STDC_HOSTED__=0"); + Builder.defineMacro("__STDC_HOSTED__", "0"); else - DefineBuiltinMacro(Buf, "__STDC_HOSTED__=1"); + Builder.defineMacro("__STDC_HOSTED__"); if (LangOpts.ObjC1) { - DefineBuiltinMacro(Buf, "__OBJC__=1"); + Builder.defineMacro("__OBJC__"); if (LangOpts.ObjCNonFragileABI) { - DefineBuiltinMacro(Buf, "__OBJC2__=1"); - DefineBuiltinMacro(Buf, "OBJC_ZEROCOST_EXCEPTIONS=1"); + Builder.defineMacro("__OBJC2__"); + Builder.defineMacro("OBJC_ZEROCOST_EXCEPTIONS"); } if (LangOpts.getGCMode() != LangOptions::NonGC) - DefineBuiltinMacro(Buf, "__OBJC_GC__=1"); + Builder.defineMacro("__OBJC_GC__"); if (LangOpts.NeXTRuntime) - DefineBuiltinMacro(Buf, "__NEXT_RUNTIME__=1"); + Builder.defineMacro("__NEXT_RUNTIME__"); } // 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"); + Builder.defineMacro("__CONSTANT_CFSTRINGS__"); if (LangOpts.ObjC2) - DefineBuiltinMacro(Buf, "OBJC_NEW_PROPERTIES"); + Builder.defineMacro("OBJC_NEW_PROPERTIES"); if (LangOpts.PascalStrings) - DefineBuiltinMacro(Buf, "__PASCAL_STRINGS__"); + Builder.defineMacro("__PASCAL_STRINGS__"); if (LangOpts.Blocks) { - DefineBuiltinMacro(Buf, "__block=__attribute__((__blocks__(byref)))"); - DefineBuiltinMacro(Buf, "__BLOCKS__=1"); + Builder.defineMacro("__block", "__attribute__((__blocks__(byref)))"); + Builder.defineMacro("__BLOCKS__"); } if (LangOpts.Exceptions) - DefineBuiltinMacro(Buf, "__EXCEPTIONS=1"); + Builder.defineMacro("__EXCEPTIONS"); if (LangOpts.CPlusPlus) { - DefineBuiltinMacro(Buf, "__DEPRECATED=1"); - DefineBuiltinMacro(Buf, "__GNUG__=4"); - DefineBuiltinMacro(Buf, "__GXX_WEAK__=1"); + Builder.defineMacro("__DEPRECATED"); + Builder.defineMacro("__GNUG__", "4"); + Builder.defineMacro("__GXX_WEAK__"); if (LangOpts.GNUMode) - DefineBuiltinMacro(Buf, "__cplusplus=1"); + Builder.defineMacro("__cplusplus"); 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"); + Builder.defineMacro("__cplusplus", "199711L"); + Builder.defineMacro("__private_extern__", "extern"); // Ugly hack to work with GNU libstdc++. - DefineBuiltinMacro(Buf, "_GNU_SOURCE=1"); + Builder.defineMacro("_GNU_SOURCE"); } if (LangOpts.Microsoft) { // Filter out some microsoft extensions when trying to parse in ms-compat // mode. - DefineBuiltinMacro(Buf, "__int8=__INT8_TYPE__"); - DefineBuiltinMacro(Buf, "__int16=__INT16_TYPE__"); - DefineBuiltinMacro(Buf, "__int32=__INT32_TYPE__"); - DefineBuiltinMacro(Buf, "__int64=__INT64_TYPE__"); + Builder.defineMacro("__int8", "__INT8_TYPE__"); + Builder.defineMacro("__int16", "__INT16_TYPE__"); + Builder.defineMacro("__int32", "__INT32_TYPE__"); + Builder.defineMacro("__int64", "__INT64_TYPE__"); // Both __PRETTY_FUNCTION__ and __FUNCTION__ are GCC extensions, however // VC++ appears to only like __FUNCTION__. - DefineBuiltinMacro(Buf, "__PRETTY_FUNCTION__=__FUNCTION__"); + Builder.defineMacro("__PRETTY_FUNCTION__", "__FUNCTION__"); // Work around some issues with Visual C++ headerws. if (LangOpts.CPlusPlus) { // Since we define wchar_t in C++ mode. - DefineBuiltinMacro(Buf, "_WCHAR_T_DEFINED=1"); - DefineBuiltinMacro(Buf, "_NATIVE_WCHAR_T_DEFINED=1"); + Builder.defineMacro("_WCHAR_T_DEFINED"); + Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED"); // FIXME: This should be temporary until we have a __pragma // solution, to avoid some errors flagged in VC++ headers. - DefineBuiltinMacro(Buf, "_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES=0"); + Builder.defineMacro("_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES", "0"); } } if (LangOpts.Optimize) - DefineBuiltinMacro(Buf, "__OPTIMIZE__=1"); + Builder.defineMacro("__OPTIMIZE__"); if (LangOpts.OptimizeSize) - DefineBuiltinMacro(Buf, "__OPTIMIZE_SIZE__=1"); + Builder.defineMacro("__OPTIMIZE_SIZE__"); // 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"); - - DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Buf); - DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Buf); - DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Buf); - DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Buf); - DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Buf); - 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()); - DefineFloatMacros(Buf, "LDBL", &TI.getLongDoubleFormat()); + Builder.defineMacro("__CHAR_BIT__", "8"); + + DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Builder); + DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder); + DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Builder); + DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder); + DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder); + DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder); + DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder); + + DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Builder); + DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Builder); + DefineTypeWidth("__INTMAX_WIDTH__", TI.getIntMaxType(), TI, Builder); + DefineType("__PTRDIFF_TYPE__", TI.getPtrDiffType(0), Builder); + DefineTypeWidth("__PTRDIFF_WIDTH__", TI.getPtrDiffType(0), TI, Builder); + DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Builder); + DefineTypeWidth("__INTPTR_WIDTH__", TI.getIntPtrType(), TI, Builder); + DefineType("__SIZE_TYPE__", TI.getSizeType(), Builder); + DefineTypeWidth("__SIZE_WIDTH__", TI.getSizeType(), TI, Builder); + DefineType("__WCHAR_TYPE__", TI.getWCharType(), Builder); + DefineTypeWidth("__WCHAR_WIDTH__", TI.getWCharType(), TI, Builder); + DefineType("__WINT_TYPE__", TI.getWIntType(), Builder); + DefineTypeWidth("__WINT_WIDTH__", TI.getWIntType(), TI, Builder); + DefineTypeWidth("__SIG_ATOMIC_WIDTH__", TI.getSigAtomicType(), TI, Builder); + + DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat()); + DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat()); + DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat()); // Define a __POINTER_WIDTH__ macro for stdint.h. - sprintf(MacroBuf, "__POINTER_WIDTH__=%d", (int)TI.getPointerWidth(0)); - DefineBuiltinMacro(Buf, MacroBuf); + Builder.defineMacro("__POINTER_WIDTH__", + llvm::Twine((int)TI.getPointerWidth(0))); if (!LangOpts.CharIsSigned) - DefineBuiltinMacro(Buf, "__CHAR_UNSIGNED__"); + Builder.defineMacro("__CHAR_UNSIGNED__"); // Define exact-width integer types for stdint.h - sprintf(MacroBuf, "__INT%d_TYPE__=char", TI.getCharWidth()); - DefineBuiltinMacro(Buf, MacroBuf); + Builder.defineMacro("__INT" + llvm::Twine(TI.getCharWidth()) + "_TYPE__", + "char"); if (TI.getShortWidth() > TI.getCharWidth()) - DefineExactWidthIntType(TargetInfo::SignedShort, TI, Buf); - + DefineExactWidthIntType(TargetInfo::SignedShort, TI, Builder); + if (TI.getIntWidth() > TI.getShortWidth()) - DefineExactWidthIntType(TargetInfo::SignedInt, TI, Buf); - + DefineExactWidthIntType(TargetInfo::SignedInt, TI, Builder); + if (TI.getLongWidth() > TI.getIntWidth()) - DefineExactWidthIntType(TargetInfo::SignedLong, TI, Buf); - + DefineExactWidthIntType(TargetInfo::SignedLong, TI, Builder); + if (TI.getLongLongWidth() > TI.getLongWidth()) - DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Buf); - + DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder); + // Add __builtin_va_list typedef. - { - const char *VAList = TI.getVAListDeclaration(); - Buf.insert(Buf.end(), VAList, VAList+strlen(VAList)); - Buf.push_back('\n'); - } + Builder.append(TI.getVAListDeclaration()); - if (const char *Prefix = TI.getUserLabelPrefix()) { - sprintf(MacroBuf, "__USER_LABEL_PREFIX__=%s", Prefix); - DefineBuiltinMacro(Buf, MacroBuf); - } + if (const char *Prefix = TI.getUserLabelPrefix()) + Builder.defineMacro("__USER_LABEL_PREFIX__", Prefix); // Build configuration options. FIXME: these should be controlled by // command line options or something. - DefineBuiltinMacro(Buf, "__FINITE_MATH_ONLY__=0"); + Builder.defineMacro("__FINITE_MATH_ONLY__", "0"); if (LangOpts.GNUInline) - DefineBuiltinMacro(Buf, "__GNUC_GNU_INLINE__=1"); + Builder.defineMacro("__GNUC_GNU_INLINE__"); else - DefineBuiltinMacro(Buf, "__GNUC_STDC_INLINE__=1"); + Builder.defineMacro("__GNUC_STDC_INLINE__"); if (LangOpts.NoInline) - DefineBuiltinMacro(Buf, "__NO_INLINE__=1"); + Builder.defineMacro("__NO_INLINE__"); if (unsigned PICLevel = LangOpts.PICLevel) { - sprintf(MacroBuf, "__PIC__=%d", PICLevel); - DefineBuiltinMacro(Buf, MacroBuf); - - sprintf(MacroBuf, "__pic__=%d", PICLevel); - DefineBuiltinMacro(Buf, MacroBuf); + Builder.defineMacro("__PIC__", llvm::Twine(PICLevel)); + Builder.defineMacro("__pic__", llvm::Twine(PICLevel)); } // Macros to control C99 numerics and <float.h> - DefineBuiltinMacro(Buf, "__FLT_EVAL_METHOD__=0"); - DefineBuiltinMacro(Buf, "__FLT_RADIX__=2"); - sprintf(MacroBuf, "__DECIMAL_DIG__=%d", - PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36)); - DefineBuiltinMacro(Buf, MacroBuf); + Builder.defineMacro("__FLT_EVAL_METHOD__", "0"); + Builder.defineMacro("__FLT_RADIX__", "2"); + int Dig = PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36); + Builder.defineMacro("__DECIMAL_DIG__", llvm::Twine(Dig)); if (LangOpts.getStackProtectorMode() == LangOptions::SSPOn) - DefineBuiltinMacro(Buf, "__SSP__=1"); + Builder.defineMacro("__SSP__"); else if (LangOpts.getStackProtectorMode() == LangOptions::SSPReq) - DefineBuiltinMacro(Buf, "__SSP_ALL__=2"); + Builder.defineMacro("__SSP_ALL__", "2"); + if (FEOpts.ProgramAction == frontend::RewriteObjC) + Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))"); // Get other target #defines. - TI.getTargetDefines(LangOpts, Buf); + TI.getTargetDefines(LangOpts, Builder); } // Initialize the remapping of files to alternative contents, e.g., @@ -536,58 +465,55 @@ static void InitializeFileRemapping(Diagnostic &Diags, /// void clang::InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &InitOpts, - const HeaderSearchOptions &HSOpts) { - std::vector<char> PredefineBuffer; + const HeaderSearchOptions &HSOpts, + const FrontendOptions &FEOpts) { + std::string PredefineBuffer; + PredefineBuffer.reserve(4080); + llvm::raw_string_ostream Predefines(PredefineBuffer); + MacroBuilder Builder(Predefines); InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(), PP.getFileManager(), InitOpts); - const char *LineDirective = "# 1 \"<built-in>\" 3\n"; - PredefineBuffer.insert(PredefineBuffer.end(), - LineDirective, LineDirective+strlen(LineDirective)); + Builder.append("# 1 \"<built-in>\" 3"); // Install things like __POWERPC__, __GNUC__, etc into the macro table. if (InitOpts.UsePredefines) InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(), - PredefineBuffer); + FEOpts, Builder); // 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"; - PredefineBuffer.insert(PredefineBuffer.end(), - LineDirective, LineDirective+strlen(LineDirective)); + Builder.append("# 1 \"<command line>\" 1"); // Process #define's and #undef's in the order they are given. for (unsigned i = 0, e = InitOpts.Macros.size(); i != e; ++i) { if (InitOpts.Macros[i].second) // isUndef - UndefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str()); + Builder.undefineMacro(InitOpts.Macros[i].first); else - DefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str(), - &PP.getDiagnostics()); + DefineBuiltinMacro(Builder, InitOpts.Macros[i].first, + PP.getDiagnostics()); } // If -imacros are specified, include them now. These are processed before // any -include directives. for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i) - AddImplicitIncludeMacros(PredefineBuffer, InitOpts.MacroIncludes[i]); + AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]); // Process -include directives. for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) { const std::string &Path = InitOpts.Includes[i]; if (Path == InitOpts.ImplicitPTHInclude) - AddImplicitIncludePTH(PredefineBuffer, PP, Path); + AddImplicitIncludePTH(Builder, PP, Path); else - AddImplicitInclude(PredefineBuffer, Path); + AddImplicitInclude(Builder, Path); } // Exit the command line and go back to <built-in> (2 is LC_LEAVE). - LineDirective = "# 1 \"<built-in>\" 2\n"; - PredefineBuffer.insert(PredefineBuffer.end(), - LineDirective, LineDirective+strlen(LineDirective)); + Builder.append("# 1 \"<built-in>\" 2"); - // Null terminate PredefinedBuffer and add it. - PredefineBuffer.push_back(0); - PP.setPredefines(&PredefineBuffer[0]); + // Copy PredefinedBuffer into the Preprocessor. + PP.setPredefines(Predefines.str()); // Initialize the header search object. ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), HSOpts, diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index d8fd791..07d5a78 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1079,6 +1079,61 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { } } +void PCHReader::ReadDefinedMacros() { + // If there was no preprocessor block, do nothing. + if (!MacroCursor.getBitStreamReader()) + return; + + llvm::BitstreamCursor Cursor = MacroCursor; + if (Cursor.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) { + Error("malformed preprocessor block record in PCH file"); + return; + } + + RecordData Record; + while (true) { + unsigned Code = Cursor.ReadCode(); + if (Code == llvm::bitc::END_BLOCK) { + if (Cursor.ReadBlockEnd()) + Error("error at end of preprocessor block in PCH file"); + return; + } + + if (Code == llvm::bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Cursor.ReadSubBlockID(); + if (Cursor.SkipBlock()) { + Error("malformed block record in PCH file"); + return; + } + continue; + } + + if (Code == llvm::bitc::DEFINE_ABBREV) { + Cursor.ReadAbbrevRecord(); + continue; + } + + // Read a record. + const char *BlobStart; + unsigned BlobLen; + Record.clear(); + switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { + default: // Default behavior: ignore. + break; + + case pch::PP_MACRO_OBJECT_LIKE: + case pch::PP_MACRO_FUNCTION_LIKE: + DecodeIdentifierInfo(Record[0]); + break; + + case pch::PP_TOKEN: + // Ignore tokens. + break; + } + } +} + /// \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. @@ -1140,6 +1195,10 @@ PCHReader::ReadPCHBlock() { break; case pch::PREPROCESSOR_BLOCK_ID: + MacroCursor = Stream; + if (PP) + PP->setExternalSource(this); + if (Stream.SkipBlock()) { Error("malformed block record in PCH file"); return Failure; @@ -1494,7 +1553,8 @@ void PCHReader::InitializeContext(ASTContext &Ctx) { assert(PP && "Forgot to set Preprocessor ?"); PP->getIdentifierTable().setExternalIdentifierLookup(this); PP->getHeaderSearchInfo().SetExternalLookup(this); - + PP->setExternalSource(this); + // Load the translation unit declaration ReadDeclRecord(DeclOffsets[0], 0); @@ -2051,10 +2111,15 @@ void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(Record, Idx)); } void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 01e1a41..69343ed 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -208,7 +208,9 @@ void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { VisitNamedDecl(CD); - CD->setAtEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]); + SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]); + CD->setAtEndRange(SourceRange(A, B)); } void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { @@ -436,6 +438,9 @@ Attr *PCHReader::ReadAttributes() { bool IsInherited = Record[Idx++]; switch (Kind) { + default: + assert(0 && "Unknown attribute!"); + break; STRING_ATTR(Alias); UNSIGNED_ATTR(Aligned); SIMPLE_ATTR(AlwaysInline); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index ba82d26..138f1e1 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -304,6 +304,7 @@ unsigned PCHStmtReader::VisitAsmStmt(AsmStmt *S) { S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); S->setVolatile(Record[Idx++]); S->setSimple(Record[Idx++]); + S->setMSAsm(Record[Idx++]); unsigned StackIdx = StmtStack.size() - (NumOutputs*2 + NumInputs*2 + NumClobbers + 1); @@ -615,7 +616,8 @@ unsigned PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) { } } } - E->setDesignators(Designators.data(), Designators.size()); + E->setDesignators(*Reader.getContext(), + Designators.data(), Designators.size()); return NumSubExprs; } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 2875f09..3f6841b 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -344,10 +344,15 @@ void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getTypeofLoc(), Record); + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); } void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - Writer.AddSourceLocation(TL.getNameLoc(), Record); + Writer.AddSourceLocation(TL.getTypeofLoc(), Record); + Writer.AddSourceLocation(TL.getLParenLoc(), Record); + Writer.AddSourceLocation(TL.getRParenLoc(), Record); + Writer.AddTypeSourceInfo(TL.getUnderlyingTInfo(), Record); } void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); @@ -1148,7 +1153,6 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { // Loop over all the macro definitions that are live at the end of the file, // emitting each to the PP section. - // FIXME: Make sure that this sees macros defined in included PCH files. for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); I != E; ++I) { // FIXME: This emits macros in hash table order, we should do it in a stable @@ -1160,7 +1164,6 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { if (MI->isBuiltinMacro()) continue; - // FIXME: Remove this identifier reference? AddIdentifierRef(I->first, Record); MacroOffsets[I->first] = Stream.GetCurrentBitNo(); Record.push_back(MI->getDefinitionLoc().getRawEncoding()); @@ -1741,9 +1744,12 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { void PCHWriter::WriteAttributeRecord(const Attr *Attr) { RecordData Record; for (; Attr; Attr = Attr->getNext()) { - Record.push_back(Attr->getKind()); // FIXME: stable encoding + Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs Record.push_back(Attr->isInherited()); switch (Attr->getKind()) { + default: + assert(0 && "Does not support PCH writing for this attribute yet!"); + break; case Attr::Alias: AddString(cast<AliasAttr>(Attr)->getAliasee(), Record); break; diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 049cdb0..2dbcc27 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -208,7 +208,9 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { VisitNamedDecl(D); - Writer.AddSourceLocation(D->getAtEndLoc(), Record); + SourceRange R = D->getAtEndRange(); + Writer.AddSourceLocation(R.getBegin(), Record); + Writer.AddSourceLocation(R.getEnd(), Record); // Abstract class (no need to define a stable pch::DECL code). } diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index abf4eaa..4be9b81 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -277,6 +277,7 @@ void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) { Writer.AddSourceLocation(S->getRParenLoc(), Record); Record.push_back(S->isVolatile()); Record.push_back(S->isSimple()); + Record.push_back(S->isMSAsm()); Writer.WriteSubStmt(S->getAsmString()); // Outputs diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index c5dc979..95afb90 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -394,7 +394,8 @@ namespace { MultiExprArg Exprs, ExprArg AsmString, MultiExprArg Clobbers, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + bool MSAsm) { Out << __FUNCTION__ << "\n"; return StmtEmpty(); } diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index c347472..fc9401d 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/DenseSet.h" using namespace clang; using llvm::utostr; @@ -75,7 +76,9 @@ namespace { llvm::SmallVector<int, 8> ObjCBcLabelNo; // Remember all the @protocol(<expr>) expressions. llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; - + + llvm::DenseSet<uint64_t> CopyDestroyCache; + unsigned NumObjCStringLiterals; FunctionDecl *MsgSendFunctionDecl; @@ -111,6 +114,7 @@ namespace { llvm::raw_ostream* OutFile; bool SilenceRewriteMacroWarning; + bool objc_impl_method; std::string Preamble; @@ -122,6 +126,7 @@ namespace { // Block related declarations. llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls; llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls; + llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; @@ -138,6 +143,7 @@ namespace { llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; FunctionDecl *CurFunctionDef; + FunctionDecl *CurFunctionDeclToDeclareForBlock; VarDecl *GlobalVarDecl; bool DisableReplaceStmt; @@ -247,12 +253,15 @@ namespace { void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); void RewriteImplementationDecl(Decl *Dcl); void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr); + void RewriteByRefString(std::string &ResultStr, const std::string &Name, + ValueDecl *VD); void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl); void RewriteMethodDeclaration(ObjCMethodDecl *Method); void RewriteProperty(ObjCPropertyDecl *prop); void RewriteFunctionDecl(FunctionDecl *FD); + void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); void RewriteObjCQualifiedInterfaceTypes(Expr *E); bool needToScanForQualifiers(QualType T); @@ -347,7 +356,8 @@ namespace { void RewriteBlockCall(CallExpr *Exp); void RewriteBlockPointerDecl(NamedDecl *VD); void RewriteByRefVar(VarDecl *VD); - Stmt *RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD); + std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); + Stmt *RewriteBlockDeclRefExpr(Expr *VD); void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, @@ -362,7 +372,7 @@ namespace { unsigned hasCopy); Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); void SynthesizeBlockLiterals(SourceLocation FunLocStart, - const char *FunName); + const char *FunName); void RewriteRecordBody(RecordDecl *RD); void CollectBlockDeclRefInfo(BlockExpr *Exp); @@ -483,6 +493,7 @@ void RewriteObjC::Initialize(ASTContext &context) { NSStringRecord = 0; CurMethodDef = 0; CurFunctionDef = 0; + CurFunctionDeclToDeclareForBlock = 0; GlobalVarDecl = 0; SuperStructDecl = 0; ProtocolTypeDecl = 0; @@ -493,6 +504,7 @@ void RewriteObjC::Initialize(ASTContext &context) { PropParentMap = 0; CurrentBody = 0; DisableReplaceStmt = false; + objc_impl_method = false; // Get the ID and start/end of the main file. MainFileID = SM->getMainFileID(); @@ -588,8 +600,8 @@ void RewriteObjC::Initialize(ASTContext &context) { Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; Preamble += "#else\n"; - Preamble += "__OBJC_RW_DLLIMPORT \"C\" void _Block_object_assign(void *, const void *, const int);\n"; - Preamble += "__OBJC_RW_DLLIMPORT \"C\" void _Block_object_dispose(const void *, const int);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; Preamble += "#endif\n"; @@ -599,8 +611,10 @@ void RewriteObjC::Initialize(ASTContext &context) { Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; Preamble += "#define __attribute__(X)\n"; } - else + else { Preamble += "#define __block\n"; + Preamble += "#define __weak\n"; + } } @@ -779,9 +793,17 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { // as the class. As a convenience, we include the original declaration // as a comment. std::string typedefString; - typedefString += "// "; - typedefString.append(startBuf, semiPtr-startBuf+1); - typedefString += "\n"; + typedefString += "// @class "; + for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end(); + I != E; ++I) { + ObjCInterfaceDecl *ForwardDecl = I->getInterface(); + typedefString += ForwardDecl->getNameAsString(); + if (I+1 != E) + typedefString += ", "; + else + typedefString += ";\n"; + } + for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end(); I != E; ++I) { ObjCInterfaceDecl *ForwardDecl = I->getInterface(); @@ -838,7 +860,7 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { RewriteMethodDeclaration(*I); // Lastly, comment out the @end. - ReplaceText(CatDecl->getAtEndLoc(), 0, "// ", 3); + ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// ", 3); } void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { @@ -859,7 +881,7 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { RewriteMethodDeclaration(*I); // Lastly, comment out the @end. - SourceLocation LocEnd = PDecl->getAtEndLoc(); + SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); ReplaceText(LocEnd, 0, "// ", 3); // Must comment out @optional/@required @@ -1096,7 +1118,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { RewriteMethodDeclaration(*I); // Lastly, comment out the @end. - ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3); + ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// ", 3); } Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, @@ -1177,10 +1199,12 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart) { ObjCIvarDecl *D = IV->getDecl(); + const Expr *BaseExpr = IV->getBase(); if (CurMethodDef) { - if (const PointerType *pType = IV->getBase()->getType()->getAs<PointerType>()) { + if (BaseExpr->getType()->isObjCObjectPointerType() && + isa<DeclRefExpr>(BaseExpr)) { ObjCInterfaceType *iFaceDecl = - dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); + dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); // lookup which class implements the instance variable. ObjCInterfaceDecl *clsDeclared = 0; iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), @@ -1226,8 +1250,9 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // 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()->getAs<PointerType>()) { - ObjCInterfaceType *iFaceDecl = dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); + if (BaseExpr->getType()->isObjCObjectPointerType()) { + ObjCInterfaceType *iFaceDecl = + dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); // lookup which class implements the instance variable. ObjCInterfaceDecl *clsDeclared = 0; iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), @@ -1474,14 +1499,18 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, SynthCountByEnumWithState(buf); buf += ");\n\t"; buf += elementName; - buf += " = ((id)0);\n\t"; + buf += " = (("; + buf += elementTypeAsString; + buf += ")0);\n\t"; buf += "__break_label_"; buf += utostr(ObjCBcLabelNo.back()); buf += ": ;\n\t"; buf += "}\n\t"; buf += "else\n\t\t"; buf += elementName; - buf += " = ((id)0);\n"; + buf += " = (("; + buf += elementTypeAsString; + buf += ")0);\n\t"; buf += "}\n"; // Insert all these *after* the statement body. @@ -1735,10 +1764,10 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "1) { "; ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size()); sawIdTypedCatch = true; - } else if (const PointerType *pType = t->getAs<PointerType>()) { - ObjCInterfaceType *cls; // Should be a pointer to a class. - - cls = dyn_cast<ObjCInterfaceType>(pType->getPointeeType().getTypePtr()); + } else if (t->isObjCObjectPointerType()) { + QualType InterfaceTy = t->getPointeeType(); + const ObjCInterfaceType *cls = // Should be a pointer to a class. + InterfaceTy->getAs<ObjCInterfaceType>(); if (cls) { buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; buf += cls->getDecl()->getNameAsString(); @@ -2092,6 +2121,30 @@ void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { RewriteObjCQualifiedInterfaceTypes(FD); } +void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { + SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); + const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); + const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); + if (!proto) + return; + QualType Type = proto->getResultType(); + std::string FdStr = Type.getAsString(); + FdStr += " "; + FdStr += FD->getNameAsCString(); + FdStr += "("; + unsigned numArgs = proto->getNumArgs(); + for (unsigned i = 0; i < numArgs; i++) { + QualType ArgType = proto->getArgType(i); + FdStr += ArgType.getAsString(); + + if (i+1 < numArgs) + FdStr += ", "; + } + FdStr += ");\n"; + InsertText(FunLocStart, FdStr.c_str(), FdStr.size()); + CurFunctionDeclToDeclareForBlock = 0; +} + // SynthSuperContructorFunctionDecl - id objc_super(id obj, id super); void RewriteObjC::SynthSuperContructorFunctionDecl() { if (SuperContructorFunctionDecl) @@ -2946,7 +2999,6 @@ void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, std::string &Result) { if (MethodBegin == MethodEnd) return; - static bool objc_impl_method = false; if (!objc_impl_method) { /* struct _objc_method { SEL _cmd; @@ -3617,7 +3669,7 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { 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) ((long) &((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); @@ -3711,6 +3763,15 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { } } +void RewriteObjC::RewriteByRefString(std::string &ResultStr, + const std::string &Name, + ValueDecl *VD) { + assert(BlockByRefDeclNo.count(VD) && + "RewriteByRefString: ByRef decl missing"); + ResultStr += "struct __Block_byref_" + Name + + "_" + utostr(BlockByRefDeclNo[VD]) ; +} + std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, const char *funcName, std::string Tag) { @@ -3756,7 +3817,9 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); - std::string TypeString = "struct __Block_byref_" + Name + " *"; + std::string TypeString; + RewriteByRefString(TypeString, Name, (*I)); + TypeString += " *"; Name = TypeString + Name; S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; } @@ -3891,7 +3954,8 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, S += "struct __block_impl *"; Constructor += ", void *" + ArgName; } else { - std::string TypeString = "struct __Block_byref_" + FieldName; + std::string TypeString; + RewriteByRefString(TypeString, FieldName, (*I)); TypeString += " *"; FieldName = TypeString + FieldName; ArgName = TypeString + ArgName; @@ -3977,7 +4041,10 @@ std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, } void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, - const char *FunName) { + const char *FunName) { + // Insert declaration for the function in which block literal is used. + if (CurFunctionDeclToDeclareForBlock) + RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); // Insert closures that were part of the function. for (unsigned i = 0; i < Blocks.size(); i++) { @@ -4192,29 +4259,40 @@ void RewriteObjC::RewriteBlockCall(CallExpr *Exp) { // i = 77; // }; //} -Stmt *RewriteObjC::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) { +Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR - // for each BDRE where BYREFVAR is name of the variable. + // for each DeclRefExp where BYREFVAR is name of the variable. + ValueDecl *VD; + bool isArrow = true; + if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp)) + VD = BDRE->getDecl(); + else { + VD = cast<DeclRefExpr>(DeclRefExp)->getDecl(); + isArrow = false; + } + FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), &Context->Idents.get("__forwarding"), Context->VoidPtrTy, 0, /*BitWidth=*/0, /*Mutable=*/true); - MemberExpr *ME = new (Context) MemberExpr(BDRE, true, FD, SourceLocation(), + MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow, + FD, SourceLocation(), FD->getType()); - const char *Name = BDRE->getDecl()->getNameAsCString(); + + const char *Name = VD->getNameAsCString(); FD = FieldDecl::Create(*Context, 0, SourceLocation(), &Context->Idents.get(Name), Context->VoidPtrTy, 0, /*BitWidth=*/0, /*Mutable=*/true); ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(), - BDRE->getType()); + DeclRefExp->getType()); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), ME); - ReplaceStmt(BDRE, PE); + ReplaceStmt(DeclRefExp, PE); return PE; } @@ -4369,6 +4447,64 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { return; } + +/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: +/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, +/// struct Block_byref_id_object *src) { +/// _Block_object_assign (&_dest->object, _src->object, +/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT +/// [|BLOCK_FIELD_IS_WEAK]) // object +/// _Block_object_assign(&_dest->object, _src->object, +/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK +/// [|BLOCK_FIELD_IS_WEAK]) // block +/// } +/// And: +/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { +/// _Block_object_dispose(_src->object, +/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT +/// [|BLOCK_FIELD_IS_WEAK]) // object +/// _Block_object_dispose(_src->object, +/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK +/// [|BLOCK_FIELD_IS_WEAK]) // block +/// } + +std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, + int flag) { + std::string S; + if (CopyDestroyCache.count(flag)) + return S; + CopyDestroyCache.insert(flag); + S = "static void __Block_byref_id_object_copy_"; + S += utostr(flag); + S += "(void *dst, void *src) {\n"; + + // offset into the object pointer is computed as: + // void * + void* + int + int + void* + void * + unsigned IntSize = + static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); + unsigned VoidPtrSize = + static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); + + unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/8; + S += " _Block_object_assign((char*)dst + "; + S += utostr(offset); + S += ", *(void * *) ((char*)src + "; + S += utostr(offset); + S += "), "; + S += utostr(flag); + S += ");\n}\n"; + + S += "static void __Block_byref_id_object_dispose_"; + S += utostr(flag); + S += "(void *src) {\n"; + S += " _Block_object_dispose(*(void * *) ((char*)src + "; + S += utostr(offset); + S += "), "; + S += utostr(flag); + S += ");\n}\n"; + return S; +} + /// RewriteByRefVar - For each __block typex ND variable this routine transforms /// the declaration into: /// struct __Block_byref_ND { @@ -4376,8 +4512,8 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { /// struct __Block_byref_ND *__forwarding; /// int32_t __flags; /// int32_t __size; -/// void *__ByrefKeepFuncPtr; // Only if variable is __block ObjC object -/// void *__ByrefDestroyFuncPtr; // Only if variable is __block ObjC object +/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object +/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object /// typex ND; /// }; /// @@ -4388,54 +4524,110 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { /// /// void RewriteObjC::RewriteByRefVar(VarDecl *ND) { + // Insert declaration for the function in which block literal is + // used. + if (CurFunctionDeclToDeclareForBlock) + RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); + int flag = 0; + int isa = 0; SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); const char *startBuf = SM->getCharacterData(DeclLoc); SourceLocation X = ND->getLocEnd(); X = SM->getInstantiationLoc(X); const char *endBuf = SM->getCharacterData(X); std::string Name(ND->getNameAsString()); - std::string ByrefType = "struct __Block_byref_"; - ByrefType += Name; + std::string ByrefType; + RewriteByRefString(ByrefType, Name, ND); ByrefType += " {\n"; ByrefType += " void *__isa;\n"; - ByrefType += " struct __Block_byref_" + Name + " *__forwarding;\n"; + RewriteByRefString(ByrefType, Name, ND); + ByrefType += " *__forwarding;\n"; ByrefType += " int __flags;\n"; ByrefType += " int __size;\n"; - // FIXME. Add void *__ByrefKeepFuncPtr; void *__ByrefDestroyFuncPtr; - // if needed. - ND->getType().getAsStringInternal(Name, Context->PrintingPolicy); + // Add void *__Block_byref_id_object_copy; + // void *__Block_byref_id_object_dispose; if needed. + QualType Ty = ND->getType(); + bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty); + if (HasCopyAndDispose) { + ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; + ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; + } + + Ty.getAsStringInternal(Name, Context->PrintingPolicy); ByrefType += " " + Name + ";\n"; ByrefType += "};\n"; // Insert this type in global scope. It is needed by helper function. assert(CurFunctionDef && "RewriteByRefVar - CurFunctionDef is null"); SourceLocation FunLocStart = CurFunctionDef->getTypeSpecStartLoc(); InsertText(FunLocStart, ByrefType.c_str(), ByrefType.size()); + if (Ty.isObjCGCWeak()) { + flag |= BLOCK_FIELD_IS_WEAK; + isa = 1; + } + + if (HasCopyAndDispose) { + flag = BLOCK_BYREF_CALLER; + QualType Ty = ND->getType(); + // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. + if (Ty->isBlockPointerType()) + flag |= BLOCK_FIELD_IS_BLOCK; + else + flag |= BLOCK_FIELD_IS_OBJECT; + std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); + if (!HF.empty()) + InsertText(FunLocStart, HF.c_str(), HF.size()); + } // struct __Block_byref_ND ND = // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), // initializer-if-any}; bool hasInit = (ND->getInit() != 0); + unsigned flags = 0; + if (HasCopyAndDispose) + flags |= BLOCK_HAS_COPY_DISPOSE; Name = ND->getNameAsString(); - ByrefType = "struct __Block_byref_" + Name; + ByrefType.clear(); + RewriteByRefString(ByrefType, Name, ND); if (!hasInit) { - ByrefType += " " + Name + " = "; - ByrefType += "{0, &" + Name + ", "; - // FIXME. Compute the flag. - ByrefType += "0, "; - ByrefType += "sizeof(struct __Block_byref_" + Name + ")"; + ByrefType += " " + Name + " = {(void*)"; + ByrefType += utostr(isa); + ByrefType += ", &" + Name + ", "; + ByrefType += utostr(flags); + ByrefType += ", "; + ByrefType += "sizeof("; + RewriteByRefString(ByrefType, Name, ND); + ByrefType += ")"; + if (HasCopyAndDispose) { + ByrefType += ", __Block_byref_id_object_copy_"; + ByrefType += utostr(flag); + ByrefType += ", __Block_byref_id_object_dispose_"; + ByrefType += utostr(flag); + } ByrefType += "};\n"; ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), ByrefType.c_str(), ByrefType.size()); } else { SourceLocation startLoc = ND->getInit()->getLocStart(); + startLoc = SM->getInstantiationLoc(startLoc); ByrefType += " " + Name; ReplaceText(DeclLoc, endBuf-startBuf, ByrefType.c_str(), ByrefType.size()); - ByrefType = " = {0, &" + Name + ", "; - // FIXME. Compute the flag. - ByrefType += "0, "; - ByrefType += "sizeof(struct __Block_byref_" + Name + "), "; + ByrefType = " = {(void*)"; + ByrefType += utostr(isa); + ByrefType += ", &" + Name + ", "; + ByrefType += utostr(flags); + ByrefType += ", "; + ByrefType += "sizeof("; + RewriteByRefString(ByrefType, Name, ND); + ByrefType += "), "; + if (HasCopyAndDispose) { + ByrefType += "__Block_byref_id_object_copy_"; + ByrefType += utostr(flag); + ByrefType += ", __Block_byref_id_object_dispose_"; + ByrefType += utostr(flag); + ByrefType += ", "; + } InsertText(startLoc, ByrefType.c_str(), ByrefType.size()); // Complete the newly synthesized compound expression by inserting a right @@ -4638,8 +4830,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { Stmts.push_back(S); else if (isa<ObjCForCollectionStmt>(S)) { Stmts.push_back(S); - ++BcLabelCount; - ObjCBcLabelNo.push_back(BcLabelCount); + ObjCBcLabelNo.push_back(++BcLabelCount); } SourceRange OrigStmtRange = S->getSourceRange(); @@ -4658,7 +4849,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); // Now we snarf the rewritten text and stash it away for later use. - std::string Str = Rewrite.getRewritenText(BE->getSourceRange()); + std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); RewrittenBlockExprs[BE] = Str; Stmt *blockTranscribed = SynthBlockInitExpr(BE); @@ -4801,8 +4992,13 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { else if (ND->getType()->isFunctionPointerType()) CheckFunctionPointerDecl(ND->getType(), ND); if (VarDecl *VD = dyn_cast<VarDecl>(SD)) - if (VD->hasAttr<BlocksAttr>()) + if (VD->hasAttr<BlocksAttr>()) { + static unsigned uniqueByrefDeclCount = 0; + assert(!BlockByRefDeclNo.count(ND) && + "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); + BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; RewriteByRefVar(VD); + } } if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) @@ -4829,6 +5025,12 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (BDRE->isByRef()) return RewriteBlockDeclRefExpr(BDRE); } + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { + ValueDecl *VD = DRE->getDecl(); + if (VD->hasAttr<BlocksAttr>()) + return RewriteBlockDeclRefExpr(DRE); + } + if (CallExpr *CE = dyn_cast<CallExpr>(S)) { if (CE->getCallee()->getType()->isBlockPointerType()) { Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); @@ -4885,6 +5087,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { // FIXME: If this should support Obj-C++, support CXXTryStmt if (CompoundStmt *Body = FD->getCompoundBody()) { CurFunctionDef = FD; + CurFunctionDeclToDeclareForBlock = FD; CollectPropertySetters(Body); CurrentBody = Body; Body = @@ -4899,6 +5102,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { // and any copy/dispose helper functions. InsertBlockLiteralsWithinFunction(FD); CurFunctionDef = 0; + CurFunctionDeclToDeclareForBlock = 0; } return; } diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 61f8a70..fcefd4e 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -371,7 +371,7 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, 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. + // them to spaces and update the CaretLine to match. for (unsigned i = 0; i != SourceLine.size(); ++i) { if (SourceLine[i] != '\t') continue; @@ -379,8 +379,11 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, 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"); + unsigned TabStop = DiagOpts->TabStop; + assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop && + "Invalid -ftabstop value"); + unsigned NumSpaces = ((i+TabStop)/TabStop * TabStop) - (i+1); + assert(NumSpaces < TabStop && "Invalid computation of space amt"); // Insert spaces into the SourceLine. SourceLine.insert(i+1, NumSpaces, ' '); |