aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-01-15 15:39:40 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-01-15 15:39:40 +0000
commitee791dde723a2089c681d2ab6a9d4f96379d5f49 (patch)
treea6082d4d1d1e9ddaea09a6a04bb4a47da95d642d /lib/Frontend
parentabe15e553e58165e7692c0d0842865c488ed7b45 (diff)
downloadsrc-ee791dde723a2089c681d2ab6a9d4f96379d5f49.tar.gz
src-ee791dde723a2089c681d2ab6a9d4f96379d5f49.zip
Notes
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTConsumers.cpp13
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp12
-rw-r--r--lib/Frontend/CompilerInstance.cpp93
-rw-r--r--lib/Frontend/CompilerInvocation.cpp17
-rw-r--r--lib/Frontend/FixItRewriter.cpp3
-rw-r--r--lib/Frontend/FrontendActions.cpp4
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp6
-rw-r--r--lib/Frontend/InitPreprocessor.cpp442
-rw-r--r--lib/Frontend/PCHReader.cpp71
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp7
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp4
-rw-r--r--lib/Frontend/PCHWriter.cpp16
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp4
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp1
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp3
-rw-r--r--lib/Frontend/RewriteObjC.cpp314
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp9
17 files changed, 674 insertions, 345 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index f1a666646ff9..52b597e8d273 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 6824d8f4eb40..ad152d33bcb2 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 2a6a8a8750d2..19c740d17a83 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 63f66fa54487..0bca4754ec11 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 4fa2b3c51eb5..0b04cf2b44d3 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 4c647fda2b6d..0baba3f4673a 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 95551252002a..6fceb98567b0 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 c1fc92d3b0c9..e4c380ae0edd 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 d8fd791b1905..07d5a78beaeb 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 01e1a4191a99..69343ed48c4b 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 ba82d2601026..138f1e141b09 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 2875f0930c42..3f6841b54576 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 049cdb03ea3b..2dbcc27f95ba 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 abf4eaa0f8aa..4be9b817ed82 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 c5dc979f654b..95afb908dfa1 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 c3474728a6ed..fc9401d29001 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 61f8a70fffff..fcefd4e35822 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, ' ');