aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-12-15 18:49:47 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-12-15 18:49:47 +0000
commit34d02d0b37f16015f317a935c48ce8b7b64ae77b (patch)
tree2fd5819f49caecc5f520219b6b9254fe94ebb138 /lib/Frontend
parent1569ce68681d909594d64f9b056d71f5dd7563bf (diff)
downloadsrc-34d02d0b37f16015f317a935c48ce8b7b64ae77b.tar.gz
src-34d02d0b37f16015f317a935c48ce8b7b64ae77b.zip
Notes
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTConsumers.cpp9
-rw-r--r--lib/Frontend/ASTUnit.cpp130
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp38
-rw-r--r--lib/Frontend/Backend.cpp101
-rw-r--r--lib/Frontend/CompilerInstance.cpp14
-rw-r--r--lib/Frontend/CompilerInvocation.cpp89
-rw-r--r--lib/Frontend/DiagChecker.cpp10
-rw-r--r--lib/Frontend/FixItRewriter.cpp2
-rw-r--r--lib/Frontend/FrontendAction.cpp8
-rw-r--r--lib/Frontend/FrontendActions.cpp51
-rw-r--r--lib/Frontend/HTMLPrint.cpp4
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp140
-rw-r--r--lib/Frontend/InitPreprocessor.cpp82
-rw-r--r--lib/Frontend/LangStandards.cpp4
-rw-r--r--lib/Frontend/PCHReader.cpp37
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp9
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp6
-rw-r--r--lib/Frontend/PCHWriter.cpp22
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp20
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp2
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp39
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp60
-rw-r--r--lib/Frontend/RewriteObjC.cpp312
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp49
24 files changed, 861 insertions, 377 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 9a30f59465f8..f1a666646ff9 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -28,8 +28,6 @@
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
-#include <cstdio>
-
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -405,8 +403,13 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
Out << "<objc property> " << OPD->getNameAsString() << "\n";
break;
}
+ case Decl::FunctionTemplate: {
+ FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
+ Out << "<function template> " << FTD->getNameAsString() << "\n";
+ break;
+ }
default:
- fprintf(stderr, "DeclKind: %d \"%s\"\n", DK, I->getDeclKindName());
+ Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
assert(0 && "decl unhandled");
}
}
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index f647c8a23705..48296c7289e3 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -17,27 +17,29 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
-#include "llvm/LLVMContext.h"
+#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
using namespace clang;
-ASTUnit::ASTUnit(DiagnosticClient *diagClient) : tempFile(false) {
- Diags.setClient(diagClient ? diagClient : new TextDiagnosticBuffer());
+ASTUnit::ASTUnit(bool _MainFileIsAST)
+ : tempFile(false), MainFileIsAST(_MainFileIsAST) {
}
ASTUnit::~ASTUnit() {
if (tempFile)
llvm::sys::Path(getPCHFileName()).eraseFromDisk();
-
- // The ASTUnit object owns the DiagnosticClient.
- delete Diags.getClient();
}
namespace {
@@ -90,19 +92,19 @@ public:
} // anonymous namespace
const std::string &ASTUnit::getOriginalSourceFileName() {
- return dyn_cast<PCHReader>(Ctx->getExternalSource())->getOriginalSourceFile();
+ return OriginalSourceFile;
}
const std::string &ASTUnit::getPCHFileName() {
+ assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
return dyn_cast<PCHReader>(Ctx->getExternalSource())->getFileName();
}
ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
- std::string *ErrMsg,
- DiagnosticClient *diagClient,
+ Diagnostic &Diags,
bool OnlyLocalDecls,
bool UseBumpAllocator) {
- llvm::OwningPtr<ASTUnit> AST(new ASTUnit(diagClient));
+ llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
@@ -118,7 +120,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
llvm::OwningPtr<ExternalASTSource> Source;
Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
- AST->Diags));
+ Diags));
Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
Predefines, Counter));
@@ -128,11 +130,12 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
case PCHReader::Failure:
case PCHReader::IgnorePCH:
- if (ErrMsg)
- *ErrMsg = "Could not load PCH file";
+ Diags.Report(diag::err_fe_unable_to_load_pch);
return NULL;
}
+ AST->OriginalSourceFile = Reader->getOriginalSourceFile();
+
// PCH loaded successfully. Now create the preprocessor.
// Get information about the target being compiled for.
@@ -143,8 +146,8 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
TargetOpts.CPU = "";
TargetOpts.Features.clear();
TargetOpts.Triple = TargetTriple;
- AST->Target.reset(TargetInfo::CreateTargetInfo(AST->Diags, TargetOpts));
- AST->PP.reset(new Preprocessor(AST->Diags, LangInfo, *AST->Target.get(),
+ AST->Target.reset(TargetInfo::CreateTargetInfo(Diags, TargetOpts));
+ AST->PP.reset(new Preprocessor(Diags, LangInfo, *AST->Target.get(),
AST->getSourceManager(), HeaderInfo));
Preprocessor &PP = *AST->PP.get();
@@ -177,13 +180,30 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
namespace {
-class NullAction : public ASTFrontendAction {
+class TopLevelDeclTrackerConsumer : public ASTConsumer {
+ ASTUnit &Unit;
+
+public:
+ TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
+
+ void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it)
+ Unit.getTopLevelDecls().push_back(*it);
+ }
+};
+
+class TopLevelDeclTrackerAction : public ASTFrontendAction {
+public:
+ ASTUnit &Unit;
+
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile) {
- return new ASTConsumer();
+ return new TopLevelDeclTrackerConsumer(Unit);
}
public:
+ TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
+
virtual bool hasCodeCompletionSupport() const { return false; }
};
@@ -191,12 +211,11 @@ public:
ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI,
Diagnostic &Diags,
- bool OnlyLocalDecls,
- bool UseBumpAllocator) {
+ bool OnlyLocalDecls) {
// Create the compiler instance to use for building the AST.
- CompilerInstance Clang(&llvm::getGlobalContext(), false);
+ CompilerInstance Clang;
llvm::OwningPtr<ASTUnit> AST;
- NullAction Act;
+ llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
Clang.getInvocation() = CI;
@@ -221,9 +240,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI,
"FIXME: AST inputs not yet supported here!");
// Create the AST unit.
- //
- // FIXME: Use the provided diagnostic client.
- AST.reset(new ASTUnit());
+ AST.reset(new ASTUnit(false));
+
+ AST->OnlyLocalDecls = OnlyLocalDecls;
+ AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
// Create a file manager object to provide access to and cache the filesystem.
Clang.setFileManager(&AST->getFileManager());
@@ -234,20 +254,22 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(const CompilerInvocation &CI,
// Create the preprocessor.
Clang.createPreprocessor();
- if (!Act.BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
+ Act.reset(new TopLevelDeclTrackerAction(*AST));
+ if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
/*IsAST=*/false))
goto error;
- Act.Execute();
+ Act->Execute();
- // Steal the created context and preprocessor, and take back the source and
- // file managers.
+ // Steal the created target, context, and preprocessor, and take back the
+ // source and file managers.
AST->Ctx.reset(Clang.takeASTContext());
AST->PP.reset(Clang.takePreprocessor());
Clang.takeSourceManager();
Clang.takeFileManager();
+ AST->Target.reset(Clang.takeTarget());
- Act.EndSourceFile();
+ Act->EndSourceFile();
Clang.takeDiagnosticClient();
Clang.takeDiagnostics();
@@ -261,3 +283,53 @@ error:
Clang.takeDiagnostics();
return 0;
}
+
+ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
+ const char **ArgEnd,
+ Diagnostic &Diags,
+ llvm::StringRef ResourceFilesPath,
+ bool OnlyLocalDecls,
+ bool UseBumpAllocator) {
+ llvm::SmallVector<const char *, 16> Args;
+ Args.push_back("<clang>"); // FIXME: Remove dummy argument.
+ Args.insert(Args.end(), ArgBegin, ArgEnd);
+
+ // FIXME: Find a cleaner way to force the driver into restricted modes. We
+ // also want to force it to use clang.
+ Args.push_back("-fsyntax-only");
+
+ // FIXME: We shouldn't have to pass in the path info.
+ driver::Driver TheDriver("clang", "/", llvm::sys::getHostTriple(),
+ "a.out", false, Diags);
+ llvm::OwningPtr<driver::Compilation> C(
+ TheDriver.BuildCompilation(Args.size(), Args.data()));
+
+ // We expect to get back exactly one command job, if we didn't something
+ // failed.
+ const driver::JobList &Jobs = C->getJobs();
+ if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
+ llvm::SmallString<256> Msg;
+ llvm::raw_svector_ostream OS(Msg);
+ C->PrintJob(OS, C->getJobs(), "; ", true);
+ Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
+ return 0;
+ }
+
+ const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
+ if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
+ Diags.Report(diag::err_fe_expected_clang_command);
+ return 0;
+ }
+
+ const driver::ArgStringList &CCArgs = Cmd->getArguments();
+ CompilerInvocation CI;
+ CompilerInvocation::CreateFromArgs(CI, (const char**) CCArgs.data(),
+ (const char**) CCArgs.data()+CCArgs.size(),
+ Diags);
+
+ // Override the resources path.
+ CI.getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
+
+ CI.getFrontendOpts().DisableFree = UseBumpAllocator;
+ return LoadFromCompilerInvocation(CI, Diags, OnlyLocalDecls);
+}
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 5df1eceb8850..a74bbc24ee10 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -139,13 +139,17 @@ public:
return;
declDisplayed = true;
- // FIXME: Is getCodeDecl() always a named decl?
+ SourceManager &SM = Mgr->getASTContext().getSourceManager();
+ PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
+ llvm::errs() << "ANALYZE: " << Loc.getFilename();
+
if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
const NamedDecl *ND = cast<NamedDecl>(D);
- SourceManager &SM = Mgr->getASTContext().getSourceManager();
- llvm::errs() << "ANALYZE: "
- << SM.getPresumedLoc(ND->getLocation()).getFilename()
- << ' ' << ND->getNameAsString() << '\n';
+ llvm::errs() << ' ' << ND->getNameAsString() << '\n';
+ }
+ else if (isa<BlockDecl>(D)) {
+ llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
+ << Loc.getColumn() << '\n';
}
}
@@ -167,7 +171,6 @@ public:
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
- Opts.AnalyzerDisplayProgress,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
Opts.TrimGraph));
@@ -265,10 +268,21 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
// Explicitly destroy the PathDiagnosticClient. This will flush its output.
// FIXME: This should be replaced with something that doesn't rely on
- // side-effects in PathDiagnosticClient's destructor.
+ // side-effects in PathDiagnosticClient's destructor. This is required when
+ // used with option -disable-free.
Mgr.reset(NULL);
}
+static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
+ if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ WL.push_back(BD);
+
+ for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
+ I!=E; ++I)
+ if (DeclContext *DC = dyn_cast<DeclContext>(*I))
+ FindBlocks(DC, WL);
+}
+
void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Don't run the actions if an error has occured with parsing the file.
@@ -285,8 +299,16 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
Mgr->ClearContexts();
// Dispatch on the actions.
+ llvm::SmallVector<Decl*, 10> WL;
+ WL.push_back(D);
+
+ if (Body && Opts.AnalyzeNestedBlocks)
+ FindBlocks(cast<DeclContext>(D), WL);
+
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
- (*I)(*this, *Mgr, D);
+ for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
+ WI != WE; ++WI)
+ (*I)(*this, *Mgr, *WI);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp
index 9dc109da65ef..9be6786b5f75 100644
--- a/lib/Frontend/Backend.cpp
+++ b/lib/Frontend/Backend.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/TargetOptions.h"
#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
@@ -31,12 +32,14 @@
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegistry.h"
using namespace clang;
using namespace llvm;
namespace {
class BackendConsumer : public ASTConsumer {
+ Diagnostic &Diags;
BackendAction Action;
const CodeGenOptions &CodeGenOpts;
const LangOptions &LangOpts;
@@ -64,21 +67,20 @@ namespace {
void CreatePasses();
- /// AddEmitPasses - Add passes necessary to emit assembly or LLVM
- /// IR.
+ /// AddEmitPasses - Add passes necessary to emit assembly or LLVM IR.
///
- /// \return True on success. On failure \arg Error will be set to
- /// a user readable error message.
- bool AddEmitPasses(std::string &Error);
+ /// \return True on success.
+ bool AddEmitPasses();
void EmitAssembly();
public:
- BackendConsumer(BackendAction action, Diagnostic &Diags,
+ BackendConsumer(BackendAction action, Diagnostic &_Diags,
const LangOptions &langopts, const CodeGenOptions &compopts,
const TargetOptions &targetopts, bool TimePasses,
const std::string &infile, llvm::raw_ostream *OS,
LLVMContext& C) :
+ Diags(_Diags),
Action(action),
CodeGenOpts(compopts),
LangOpts(langopts),
@@ -195,7 +197,7 @@ FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
return PerFunctionPasses;
}
-bool BackendConsumer::AddEmitPasses(std::string &Error) {
+bool BackendConsumer::AddEmitPasses() {
if (Action == Backend_EmitNothing)
return true;
@@ -207,48 +209,68 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
bool Fast = CodeGenOpts.OptimizationLevel == 0;
// Create the TargetMachine for generating code.
+ std::string Error;
std::string Triple = TheModule->getTargetTriple();
const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
if (!TheTarget) {
- Error = std::string("Unable to get target machine: ") + Error;
+ Diags.Report(diag::err_fe_unable_to_create_target) << Error;
return false;
}
// FIXME: Expose these capabilities via actual APIs!!!! Aside from just
// being gross, this is also totally broken if we ever care about
// concurrency.
+ llvm::NoFramePointerElim = CodeGenOpts.DisableFPElim;
+ if (CodeGenOpts.FloatABI == "soft")
+ llvm::FloatABIType = llvm::FloatABI::Soft;
+ else if (CodeGenOpts.FloatABI == "hard")
+ llvm::FloatABIType = llvm::FloatABI::Hard;
+ else {
+ assert(CodeGenOpts.FloatABI.empty() && "Invalid float abi!");
+ llvm::FloatABIType = llvm::FloatABI::Default;
+ }
+ NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
+ llvm::UseSoftFloat = CodeGenOpts.SoftFloat;
+ UnwindTablesMandatory = CodeGenOpts.UnwindTables;
+
+ TargetMachine::setAsmVerbosityDefault(CodeGenOpts.AsmVerbose);
+
+ // FIXME: Parse this earlier.
+ if (CodeGenOpts.RelocationModel == "static") {
+ TargetMachine::setRelocationModel(llvm::Reloc::Static);
+ } else if (CodeGenOpts.RelocationModel == "pic") {
+ TargetMachine::setRelocationModel(llvm::Reloc::PIC_);
+ } else {
+ assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" &&
+ "Invalid PIC model!");
+ TargetMachine::setRelocationModel(llvm::Reloc::DynamicNoPIC);
+ }
+ // FIXME: Parse this earlier.
+ if (CodeGenOpts.CodeModel == "small") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Small);
+ } else if (CodeGenOpts.CodeModel == "kernel") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Kernel);
+ } else if (CodeGenOpts.CodeModel == "medium") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Medium);
+ } else if (CodeGenOpts.CodeModel == "large") {
+ TargetMachine::setCodeModel(llvm::CodeModel::Large);
+ } else {
+ assert(CodeGenOpts.CodeModel.empty() && "Invalid code model!");
+ TargetMachine::setCodeModel(llvm::CodeModel::Default);
+ }
+
std::vector<const char *> BackendArgs;
BackendArgs.push_back("clang"); // Fake program name.
- if (CodeGenOpts.AsmVerbose)
- BackendArgs.push_back("-asm-verbose");
- if (!CodeGenOpts.CodeModel.empty()) {
- BackendArgs.push_back("-code-model");
- BackendArgs.push_back(CodeGenOpts.CodeModel.c_str());
- }
if (!CodeGenOpts.DebugPass.empty()) {
BackendArgs.push_back("-debug-pass");
BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());
}
- if (CodeGenOpts.DisableFPElim)
- BackendArgs.push_back("-disable-fp-elim");
- if (!CodeGenOpts.FloatABI.empty()) {
- BackendArgs.push_back("-float-abi");
- BackendArgs.push_back(CodeGenOpts.FloatABI.c_str());
- }
if (!CodeGenOpts.LimitFloatPrecision.empty()) {
BackendArgs.push_back("-limit-float-precision");
BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
}
- if (CodeGenOpts.NoZeroInitializedInBSS)
- BackendArgs.push_back("-nozero-initialized-in-bss");
- if (CodeGenOpts.SoftFloat)
- BackendArgs.push_back("-soft-float");
- BackendArgs.push_back("-relocation-model");
- BackendArgs.push_back(CodeGenOpts.RelocationModel.c_str());
if (llvm::TimePassesIsEnabled)
BackendArgs.push_back("-time-passes");
- if (CodeGenOpts.UnwindTables)
- BackendArgs.push_back("-unwind-tables");
BackendArgs.push_back(0);
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
(char**) &BackendArgs[0]);
@@ -290,7 +312,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
TargetMachine::AssemblyFile, OptLevel)) {
default:
case FileModel::Error:
- Error = "Unable to interface with target machine!\n";
+ Diags.Report(diag::err_fe_unable_to_interface_with_target);
return false;
case FileModel::AsmFile:
break;
@@ -298,7 +320,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
if (TM->addPassesToEmitFileFinish(*CodeGenPasses, (MachineCodeEmitter *)0,
OptLevel)) {
- Error = "Unable to interface with target machine!\n";
+ Diags.Report(diag::err_fe_unable_to_interface_with_target);
return false;
}
}
@@ -329,8 +351,14 @@ void BackendConsumer::CreatePasses() {
switch (Inlining) {
case CodeGenOptions::NoInlining: break;
case CodeGenOptions::NormalInlining: {
- // Inline small functions
- unsigned Threshold = (CodeGenOpts.OptimizeSize || OptLevel < 3) ? 50 : 200;
+ // Set the inline threshold following llvm-gcc.
+ //
+ // FIXME: Derive these constants in a principled fashion.
+ unsigned Threshold = 200;
+ if (CodeGenOpts.OptimizeSize)
+ Threshold = 50;
+ else if (OptLevel > 2)
+ Threshold = 250;
InliningPass = createFunctionInliningPass(Threshold);
break;
}
@@ -372,13 +400,8 @@ void BackendConsumer::EmitAssembly() {
assert(TheModule == M && "Unexpected module change during IR generation");
CreatePasses();
-
- std::string Error;
- if (!AddEmitPasses(Error)) {
- // FIXME: Don't fail this way.
- llvm::errs() << "ERROR: " << Error << "\n";
- ::exit(1);
- }
+ if (!AddEmitPasses())
+ return;
// Run passes. For now we do all passes at once, but eventually we
// would like to have the option of streaming code generation.
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 1083d5ef1c02..2a6a8a8750d2 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -95,7 +95,7 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
return;
}
- (*OS) << "clang-cc command line arguments: ";
+ (*OS) << "clang -cc1 command line arguments: ";
for (unsigned i = 0; i != argc; ++i)
(*OS) << argv[i] << ' ';
(*OS) << '\n';
@@ -172,10 +172,6 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
if (!PPOpts.TokenCache.empty())
PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
- // FIXME: Don't fail like this.
- if (Diags.hasErrorOccurred())
- exit(1);
-
// Create the Preprocessor.
HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
@@ -287,7 +283,7 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
}
// Truncate the named file at the given line/column.
- PP.getSourceManager().truncateFileAt(Entry, Line, Column);
+ PP.SetCodeCompletionPoint(Entry, Line, Column);
// Set up the creation routine for code-completion.
if (UseDebugPrinter)
@@ -332,9 +328,9 @@ CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
InFile, Extension,
&OutputPathName);
if (!OS) {
- // FIXME: Don't fail this way.
- llvm::errs() << "error: " << Error << "\n";
- ::exit(1);
+ getDiagnostics().Report(diag::err_fe_unable_to_open_output)
+ << OutputPath << Error;
+ return 0;
}
// Add the output file -- but don't try to remove "-", since this means we are
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index c5375079506b..7a3388ffbb97 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -31,7 +31,7 @@ using namespace clang;
static const char *getAnalysisName(Analyses Kind) {
switch (Kind) {
default:
- llvm::llvm_unreachable("Unknown analysis store!");
+ llvm_unreachable("Unknown analysis kind!");
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
case NAME: return "-" CMDFLAG;
#include "clang/Frontend/Analyses.def"
@@ -41,7 +41,7 @@ static const char *getAnalysisName(Analyses Kind) {
static const char *getAnalysisStoreName(AnalysisStores Kind) {
switch (Kind) {
default:
- llvm::llvm_unreachable("Unknown analysis store!");
+ llvm_unreachable("Unknown analysis store!");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
case NAME##Model: return CMDFLAG;
#include "clang/Frontend/Analyses.def"
@@ -51,7 +51,7 @@ static const char *getAnalysisStoreName(AnalysisStores Kind) {
static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
switch (Kind) {
default:
- llvm::llvm_unreachable("Unknown analysis constraints!");
+ llvm_unreachable("Unknown analysis constraints!");
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
case NAME##Model: return CMDFLAG;
#include "clang/Frontend/Analyses.def"
@@ -61,7 +61,7 @@ static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
switch (Kind) {
default:
- llvm::llvm_unreachable("Unknown analysis client!");
+ llvm_unreachable("Unknown analysis client!");
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
case PD_##NAME: return CMDFLAG;
#include "clang/Frontend/Analyses.def"
@@ -96,6 +96,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
Res.push_back("-analyzer-opt-analyze-headers");
if (Opts.AnalyzerDisplayProgress)
Res.push_back("-analyzer-display-progress");
+ if (Opts.AnalyzeNestedBlocks)
+ Res.push_back("-analyzer-opt-analyze-nested-blocks");
if (Opts.EagerlyAssume)
Res.push_back("-analyzer-eagerly-assume");
if (!Opts.PurgeDead)
@@ -244,7 +246,7 @@ static const char *getInputKindName(FrontendOptions::InputKind Kind) {
case FrontendOptions::IK_PreprocessedObjCXX:return "objective-c++-cpp-output";
}
- llvm::llvm_unreachable("Unexpected language kind!");
+ llvm_unreachable("Unexpected language kind!");
return 0;
}
@@ -252,7 +254,7 @@ static const char *getActionName(frontend::ActionKind Kind) {
switch (Kind) {
case frontend::PluginAction:
case frontend::InheritanceView:
- llvm::llvm_unreachable("Invalid kind!");
+ llvm_unreachable("Invalid kind!");
case frontend::ASTDump: return "-ast-dump";
case frontend::ASTPrint: return "-ast-print";
@@ -282,7 +284,7 @@ static const char *getActionName(frontend::ActionKind Kind) {
case frontend::RunPreprocessorOnly: return "-Eonly";
}
- llvm::llvm_unreachable("Unexpected language kind!");
+ llvm_unreachable("Unexpected language kind!");
return 0;
}
@@ -296,12 +298,16 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts,
Res.push_back("-empty-input-only");
if (Opts.RelocatablePCH)
Res.push_back("-relocatable-pch");
+ if (Opts.ShowHelp)
+ Res.push_back("-help");
if (Opts.ShowMacrosInCodeCompletion)
Res.push_back("-code-completion-macros");
if (Opts.ShowStats)
Res.push_back("-print-stats");
if (Opts.ShowTimers)
Res.push_back("-ftime-report");
+ if (Opts.ShowVersion)
+ Res.push_back("-version");
bool NeedLang = false;
for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
@@ -345,6 +351,10 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts,
Res.push_back("-plugin");
Res.push_back(Opts.ActionName);
}
+ for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i) {
+ Res.push_back("-load");
+ Res.push_back(Opts.Plugins[i]);
+ }
}
static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
@@ -399,8 +409,9 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
// FIXME: Provide an option for this, and move env detection to driver.
llvm::llvm_report_error("Not yet implemented!");
}
- if (!Opts.BuiltinIncludePath.empty()) {
- // FIXME: Provide an option for this, and move to driver.
+ if (!Opts.ResourceDir.empty()) {
+ Res.push_back("-resource-dir");
+ Res.push_back(Opts.ResourceDir);
}
if (!Opts.UseStandardIncludes)
Res.push_back("-nostdinc");
@@ -437,6 +448,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-fno-operator-names");
if (Opts.PascalStrings)
Res.push_back("-fpascal-strings");
+ if (Opts.CatchUndefined)
+ Res.push_back("-fcatch-undefined-behavior");
if (Opts.WritableStrings)
Res.push_back("-fwritable-strings");
if (!Opts.LaxVectorConversions)
@@ -445,7 +458,7 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-faltivec");
if (Opts.Exceptions)
Res.push_back("-fexceptions");
- if (!Opts.Rtti)
+ if (!Opts.RTTI)
Res.push_back("-fno-rtti");
if (!Opts.NeXTRuntime)
Res.push_back("-fgnu-runtime");
@@ -550,6 +563,11 @@ static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
assert(Opts.ImplicitPTHInclude == Opts.TokenCache &&
"Unsupported option combination!");
}
+ for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) {
+ Res.push_back("-remap-file");
+ Res.push_back(Opts.RemappedFiles[i].first + ";" +
+ Opts.RemappedFiles[i].second);
+ }
}
static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
@@ -696,6 +714,8 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+ Opts.AnalyzeNestedBlocks =
+ Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead);
Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume);
Opts.AnalyzeSpecificFunction = getLastArgValue(Args, OPT_analyze_function);
@@ -877,10 +897,13 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) {
}
Opts.OutputFile = getLastArgValue(Args, OPT_o);
+ Opts.Plugins = getAllArgValues(Args, OPT_load);
Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch);
+ Opts.ShowHelp = Args.hasArg(OPT_help);
Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros);
Opts.ShowStats = Args.hasArg(OPT_print_stats);
Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
+ Opts.ShowVersion = Args.hasArg(OPT_version);
Opts.ViewClassInheritance = getLastArgValue(Args, OPT_cxx_inheritance_view);
FrontendOptions::InputKind DashX = FrontendOptions::IK_None;
@@ -929,8 +952,8 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) {
return DashX;
}
-static std::string GetBuiltinIncludePath(const char *Argv0,
- void *MainAddr) {
+std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
+ void *MainAddr) {
llvm::sys::Path P = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr);
if (!P.isEmpty()) {
@@ -941,22 +964,18 @@ static std::string GetBuiltinIncludePath(const char *Argv0,
P.appendComponent("lib");
P.appendComponent("clang");
P.appendComponent(CLANG_VERSION_STRING);
- P.appendComponent("include");
}
return P.str();
}
-static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
- const char *Argv0, void *MainAddr) {
+static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
using namespace cc1options;
Opts.Sysroot = getLastArgValue(Args, OPT_isysroot, "/");
Opts.Verbose = Args.hasArg(OPT_v);
+ Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
Opts.UseStandardIncludes = !Args.hasArg(OPT_nostdinc);
- Opts.BuiltinIncludePath = "";
- // FIXME: Add an option for this, its a slow call.
- if (!Args.hasArg(OPT_nobuiltininc))
- Opts.BuiltinIncludePath = GetBuiltinIncludePath(Argv0, MainAddr);
+ Opts.ResourceDir = getLastArgValue(Args, OPT_resource_dir);
// Add -I... and -F... options in order.
for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F),
@@ -1115,7 +1134,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_fno_lax_vector_conversions))
Opts.LaxVectorConversions = 0;
Opts.Exceptions = Args.hasArg(OPT_fexceptions);
- Opts.Rtti = !Args.hasArg(OPT_fno_rtti);
+ Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
Opts.Blocks = Args.hasArg(OPT_fblocks);
Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
@@ -1131,6 +1150,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.ObjCConstantStringClass = getLastArgValue(Args,
OPT_fconstant_string_class);
Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi);
+ Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
Opts.Static = Args.hasArg(OPT_static_define);
@@ -1160,7 +1180,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}
-static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args) {
+static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
+ Diagnostic &Diags) {
using namespace cc1options;
Opts.ImplicitPCHInclude = getLastArgValue(Args, OPT_include_pch);
Opts.ImplicitPTHInclude = getLastArgValue(Args, OPT_include_pth);
@@ -1188,16 +1209,27 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args) {
// PCH is handled specially, we need to extra the original include path.
if (it->getOption().matches(OPT_include_pch)) {
std::string OriginalFile =
- PCHReader::getOriginalSourceFile(it->getValue(Args));
-
- // FIXME: Don't fail like this.
+ PCHReader::getOriginalSourceFile(it->getValue(Args), Diags);
if (OriginalFile.empty())
- exit(1);
+ continue;
Opts.Includes.push_back(OriginalFile);
} else
Opts.Includes.push_back(it->getValue(Args));
}
+
+ for (arg_iterator it = Args.filtered_begin(OPT_remap_file),
+ ie = Args.filtered_end(); it != ie; ++it) {
+ std::pair<llvm::StringRef,llvm::StringRef> Split =
+ llvm::StringRef(it->getValue(Args)).split(';');
+
+ if (Split.second.empty()) {
+ Diags.Report(diag::err_drv_invalid_remap_file) << it->getAsString(Args);
+ continue;
+ }
+
+ Opts.addRemappedFile(Split.first, Split.second);
+ }
}
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
@@ -1227,8 +1259,6 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
const char **ArgBegin,
const char **ArgEnd,
- const char *Argv0,
- void *MainAddr,
Diagnostic &Diags) {
// Parse the arguments.
llvm::OwningPtr<OptTable> Opts(createCC1OptTable());
@@ -1252,11 +1282,10 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags);
FrontendOptions::InputKind DashX =
ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
- ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args,
- Argv0, MainAddr);
+ ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
if (DashX != FrontendOptions::IK_AST)
ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
- ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args);
+ ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, Diags);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
ParseTargetArgs(Res.getTargetOpts(), *Args);
}
diff --git a/lib/Frontend/DiagChecker.cpp b/lib/Frontend/DiagChecker.cpp
index e7a66b1729c4..a50cc99ab79e 100644
--- a/lib/Frontend/DiagChecker.cpp
+++ b/lib/Frontend/DiagChecker.cpp
@@ -17,7 +17,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
-#include <cstdio>
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
typedef TextDiagnosticBuffer::DiagList DiagList;
@@ -190,12 +190,10 @@ static bool PrintProblem(SourceManager &SourceMgr,
const char *Msg) {
if (diag_begin == diag_end) return false;
- fprintf(stderr, "%s\n", Msg);
-
+ llvm::errs() << Msg << "\n";
for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I)
- fprintf(stderr, " Line %d: %s\n",
- SourceMgr.getInstantiationLineNumber(I->first),
- I->second.c_str());
+ llvm::errs() << " Line " << SourceMgr.getInstantiationLineNumber(I->first)
+ << " " << I->second << "\n";
return true;
}
diff --git a/lib/Frontend/FixItRewriter.cpp b/lib/Frontend/FixItRewriter.cpp
index dddcaa97e2ff..4fa2b3c51eb5 100644
--- a/lib/Frontend/FixItRewriter.cpp
+++ b/lib/Frontend/FixItRewriter.cpp
@@ -66,7 +66,7 @@ bool FixItRewriter::WriteFixedFile(const std::string &InFileName,
Rewrite.getRewriteBufferFor(MainFileID)) {
*OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
} else {
- std::fprintf(stderr, "Main file is unchanged\n");
+ Diag(FullSourceLoc(), diag::note_fixit_main_file_unchanged);
}
OutFile->flush();
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 91c946c9cf25..96a68c931e1f 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -46,11 +46,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
assert(hasASTSupport() && "This action does not have AST support!");
std::string Error;
- ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, &Error);
- if (!AST) {
- CI.getDiagnostics().Report(diag::err_fe_invalid_ast_file) << Error;
+ ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, CI.getDiagnostics());
+ if (!AST)
goto failure;
- }
setCurrentFile(Filename, AST);
@@ -224,5 +222,5 @@ void ASTFrontendAction::ExecuteAction() {
ASTConsumer *
PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile) {
- llvm::llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
+ llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
}
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 27e194e6f108..e3c313a42299 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -35,13 +35,16 @@ ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile) {
- return CreateASTPrinter(CI.createDefaultOutputFile(false, InFile));
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
+ return CreateASTPrinter(OS);
+ return 0;
}
ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile) {
- return CreateASTPrinterXML(CI.createDefaultOutputFile(false, InFile,
- "xml"));
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
+ return CreateASTPrinterXML(OS);
+ return 0;
}
ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
@@ -74,6 +77,9 @@ ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
}
llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
+ if (!OS)
+ return 0;
+
if (CI.getFrontendOpts().RelocatablePCH)
return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
@@ -82,8 +88,9 @@ ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile) {
- return CreateHTMLPrinter(CI.createDefaultOutputFile(false, InFile),
- CI.getPreprocessor());
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
+ return CreateHTMLPrinter(OS, CI.getPreprocessor());
+ return 0;
}
ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
@@ -140,10 +147,11 @@ void FixItAction::EndSourceFileAction() {
ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile) {
- return CreateObjCRewriter(InFile,
- CI.createDefaultOutputFile(true, InFile, "cpp"),
- CI.getDiagnostics(), CI.getLangOpts(),
- CI.getDiagnosticOpts().NoRewriteMacros);
+ if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
+ return CreateObjCRewriter(InFile, OS,
+ CI.getDiagnostics(), CI.getLangOpts(),
+ CI.getDiagnosticOpts().NoRewriteMacros);
+ return 0;
}
ASTConsumer *RewriteBlocksAction::CreateASTConsumer(CompilerInstance &CI,
@@ -162,12 +170,21 @@ ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile) {
BackendAction BA = static_cast<BackendAction>(Act);
llvm::OwningPtr<llvm::raw_ostream> OS;
- if (BA == Backend_EmitAssembly)
+ switch (BA) {
+ case Backend_EmitAssembly:
OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
- else if (BA == Backend_EmitLL)
+ break;
+ case Backend_EmitLL:
OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
- else if (BA == Backend_EmitBC)
+ break;
+ case Backend_EmitBC:
OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
+ break;
+ case Backend_EmitNothing:
+ break;
+ }
+ if (BA != Backend_EmitNothing && !OS)
+ return 0;
return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(),
CI.getCodeGenOpts(), CI.getTargetOpts(),
@@ -228,6 +245,8 @@ void GeneratePTHAction::ExecuteAction() {
}
llvm::raw_fd_ostream *OS =
CI.createDefaultOutputFile(true, getCurrentFile());
+ if (!OS) return;
+
CacheTokens(CI.getPreprocessor(), OS);
}
@@ -255,6 +274,8 @@ void PrintParseAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
Preprocessor &PP = getCompilerInstance().getPreprocessor();
llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ if (!OS) return;
+
llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
Parser P(PP, *PA);
@@ -265,6 +286,8 @@ void PrintParseAction::ExecuteAction() {
void PrintPreprocessedAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ if (!OS) return;
+
DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
CI.getPreprocessorOutputOpts());
}
@@ -272,11 +295,15 @@ void PrintPreprocessedAction::ExecuteAction() {
void RewriteMacrosAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+ if (!OS) return;
+
RewriteMacrosInInput(CI.getPreprocessor(), OS);
}
void RewriteTestAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ if (!OS) return;
+
DoRewriteTest(CI.getPreprocessor(), OS);
}
diff --git a/lib/Frontend/HTMLPrint.cpp b/lib/Frontend/HTMLPrint.cpp
index 75e6184572e5..9ea8cb3feee6 100644
--- a/lib/Frontend/HTMLPrint.cpp
+++ b/lib/Frontend/HTMLPrint.cpp
@@ -41,9 +41,9 @@ namespace {
bool _SyntaxHighlight, bool _HighlightMacros)
: Out(OS), PP(pp), SyntaxHighlight(_SyntaxHighlight),
HighlightMacros(_HighlightMacros) {}
- virtual ~HTMLPrinter();
void Initialize(ASTContext &context);
+ void HandleTranslationUnit(ASTContext &Ctx);
};
}
@@ -58,7 +58,7 @@ void HTMLPrinter::Initialize(ASTContext &context) {
R.setSourceMgr(context.getSourceManager(), context.getLangOptions());
}
-HTMLPrinter::~HTMLPrinter() {
+void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
if (PP.getDiagnostics().hasErrorOccurred())
return;
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index a40a569d92f7..b4ea2576c3e6 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -21,10 +21,10 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/Config/config.h"
-#include <cstdio>
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
@@ -50,27 +50,27 @@ public:
: Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
/// AddPath - Add the specified path to the specified group list.
- void AddPath(const llvm::StringRef &Path, IncludeDirGroup Group,
+ void AddPath(const llvm::Twine &Path, IncludeDirGroup Group,
bool isCXXAware, bool isUserSupplied,
bool isFramework, bool IgnoreSysRoot = false);
/// AddGnuCPlusPlusIncludePaths - Add the necessary paths to suport a gnu
/// libstdc++.
- void AddGnuCPlusPlusIncludePaths(const std::string &Base,
- const char *ArchDir,
- const char *Dir32,
- const char *Dir64,
+ void AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef ArchDir,
+ llvm::StringRef Dir32,
+ llvm::StringRef Dir64,
const llvm::Triple &triple);
/// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW
/// libstdc++.
- void AddMinGWCPlusPlusIncludePaths(const std::string &Base,
- const char *Arch,
- const char *Version);
+ void AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef Arch,
+ llvm::StringRef Version);
/// AddDelimitedPaths - Add a list of paths delimited by the system PATH
/// separator. The processing follows that of the CPATH variable for gcc.
- void AddDelimitedPaths(const char *String);
+ void AddDelimitedPaths(llvm::StringRef String);
// AddDefaultCIncludePaths - Add paths that should always be searched.
void AddDefaultCIncludePaths(const llvm::Triple &triple);
@@ -91,25 +91,26 @@ public:
}
-void InitHeaderSearch::AddPath(const llvm::StringRef &Path,
+void InitHeaderSearch::AddPath(const llvm::Twine &Path,
IncludeDirGroup Group, bool isCXXAware,
bool isUserSupplied, bool isFramework,
bool IgnoreSysRoot) {
- assert(!Path.empty() && "can't handle empty path here");
+ assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
FileManager &FM = Headers.getFileMgr();
// Compute the actual path, taking into consideration -isysroot.
- llvm::SmallString<256> MappedPath;
+ llvm::SmallString<256> MappedPathStr;
+ llvm::raw_svector_ostream MappedPath(MappedPathStr);
// Handle isysroot.
if (Group == System && !IgnoreSysRoot) {
// FIXME: Portability. This should be a sys::Path interface, this doesn't
// handle things like C:\ right, nor win32 \\network\device\blah.
if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present.
- MappedPath.append(isysroot.begin(), isysroot.end());
+ MappedPath << isysroot;
}
- MappedPath.append(Path.begin(), Path.end());
+ Path.print(MappedPath);
// Compute the DirectoryLookup type.
SrcMgr::CharacteristicKind Type;
@@ -146,29 +147,29 @@ void InitHeaderSearch::AddPath(const llvm::StringRef &Path,
}
-void InitHeaderSearch::AddDelimitedPaths(const char *at) {
- if (*at == 0) // Empty string should not add '.' path.
+void InitHeaderSearch::AddDelimitedPaths(llvm::StringRef at) {
+ if (at.empty()) // Empty string should not add '.' path.
return;
- const char* delim = strchr(at, llvm::sys::PathSeparator);
- while (delim != 0) {
- if (delim-at == 0)
+ llvm::StringRef::size_type delim;
+ while ((delim = at.find(llvm::sys::PathSeparator)) != llvm::StringRef::npos) {
+ if (delim == 0)
AddPath(".", Angled, false, true, false);
else
- AddPath(llvm::StringRef(at, delim-at), Angled, false, true, false);
- at = delim + 1;
- delim = strchr(at, llvm::sys::PathSeparator);
+ AddPath(at.substr(0, delim), Angled, false, true, false);
+ at = at.substr(delim + 1);
}
- if (*at == 0)
+
+ if (at.empty())
AddPath(".", Angled, false, true, false);
else
AddPath(at, Angled, false, true, false);
}
-void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base,
- const char *ArchDir,
- const char *Dir32,
- const char *Dir64,
+void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef ArchDir,
+ llvm::StringRef Dir32,
+ llvm::StringRef Dir64,
const llvm::Triple &triple) {
// Add the base dir
AddPath(Base, System, true, false, false);
@@ -185,10 +186,10 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base,
AddPath(Base + "/backward", System, true, false, false);
}
-void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base,
- const char *Arch,
- const char *Version) {
- std::string localBase = Base + "/" + Arch + "/" + Version + "/include";
+void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
+ llvm::StringRef Arch,
+ llvm::StringRef Version) {
+ llvm::Twine localBase = Base + "/" + Arch + "/" + Version + "/include";
AddPath(localBase, System, true, false, false);
AddPath(localBase + "/c++", System, true, false, false);
AddPath(localBase + "/c++/backward", System, true, false, false);
@@ -258,25 +259,25 @@ bool getSystemRegistryString(const char *keyPath, const char *valueName,
int bestIndex = -1;
double bestValue = 0.0;
DWORD index, size = sizeof(keyName) - 1;
- for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
- NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
- const char *sp = keyName;
- while (*sp && !isdigit(*sp))
- sp++;
- if (!*sp)
- continue;
- const char *ep = sp + 1;
- while (*ep && (isdigit(*ep) || (*ep == '.')))
- ep++;
- char numBuf[32];
- strncpy(numBuf, sp, sizeof(numBuf) - 1);
- numBuf[sizeof(numBuf) - 1] = '\0';
- double value = strtod(numBuf, NULL);
- if (value > bestValue) {
- bestIndex = (int)index;
- bestValue = value;
- strcpy(bestName, keyName);
- }
+ for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
+ NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
+ const char *sp = keyName;
+ while (*sp && !isdigit(*sp))
+ sp++;
+ if (!*sp)
+ continue;
+ const char *ep = sp + 1;
+ while (*ep && (isdigit(*ep) || (*ep == '.')))
+ ep++;
+ char numBuf[32];
+ strncpy(numBuf, sp, sizeof(numBuf) - 1);
+ numBuf[sizeof(numBuf) - 1] = '\0';
+ double value = strtod(numBuf, NULL);
+ if (value > bestValue) {
+ bestIndex = (int)index;
+ bestValue = value;
+ strcpy(bestName, keyName);
+ }
size = sizeof(keyName) - 1;
}
// If we found the highest versioned key, open the key and get the value.
@@ -500,6 +501,10 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
"i586-redhat-linux","", "", triple);
+ // Fedora 12
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+ "i686-redhat-linux","", "", triple);
+
// openSUSE 11.1 32 bit
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
"i586-suse-linux", "", "", triple);
@@ -643,11 +648,11 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
}
if (Verbose) {
- fprintf(stderr, "ignoring duplicate directory \"%s\"\n",
- CurEntry.getName());
+ llvm::errs() << "ignoring duplicate directory \""
+ << CurEntry.getName() << "\"\n";
if (DirToRemove != i)
- fprintf(stderr, " as it is a non-system directory that duplicates"
- " a system directory\n");
+ llvm::errs() << " as it is a non-system directory that duplicates "
+ << "a system directory\n";
}
// This is reached if the current entry is a duplicate. Remove the
@@ -680,11 +685,11 @@ void InitHeaderSearch::Realize() {
// If verbose, print the list of directories that will be searched.
if (Verbose) {
- fprintf(stderr, "#include \"...\" search starts here:\n");
+ llvm::errs() << "#include \"...\" search starts here:\n";
unsigned QuotedIdx = IncludeGroup[Quoted].size();
for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
if (i == QuotedIdx)
- fprintf(stderr, "#include <...> search starts here:\n");
+ llvm::errs() << "#include <...> search starts here:\n";
const char *Name = SearchList[i].getName();
const char *Suffix;
if (SearchList[i].isNormalDir())
@@ -695,9 +700,9 @@ void InitHeaderSearch::Realize() {
assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
Suffix = " (headermap)";
}
- fprintf(stderr, " %s%s\n", Name, Suffix);
+ llvm::errs() << " " << Name << Suffix << "\n";
}
- fprintf(stderr, "End of search list.\n");
+ llvm::errs() << "End of search list.\n";
}
}
@@ -715,21 +720,22 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
}
// Add entries from CPATH and friends.
- Init.AddDelimitedPaths(HSOpts.EnvIncPath.c_str());
+ Init.AddDelimitedPaths(HSOpts.EnvIncPath);
if (Lang.CPlusPlus && Lang.ObjC1)
- Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath.c_str());
+ Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath);
else if (Lang.CPlusPlus)
- Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath.c_str());
+ Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath);
else if (Lang.ObjC1)
- Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath.c_str());
+ Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath);
else
- Init.AddDelimitedPaths(HSOpts.CEnvIncPath.c_str());
+ Init.AddDelimitedPaths(HSOpts.CEnvIncPath);
- if (!HSOpts.BuiltinIncludePath.empty()) {
+ if (HSOpts.UseBuiltinIncludes) {
// Ignore the sys root, we *always* look for clang headers relative to
// supplied path.
- Init.AddPath(HSOpts.BuiltinIncludePath, System,
- false, false, false, /*IgnoreSysRoot=*/ true);
+ llvm::sys::Path P(HSOpts.ResourceDir);
+ P.appendComponent("include");
+ Init.AddPath(P.str(), System, false, false, false, /*IgnoreSysRoot=*/ true);
}
if (HSOpts.UseStandardIncludes)
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 972c21f88d4d..c1fc92d3b0c9 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -13,17 +13,23 @@
#include "clang/Frontend/Utils.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/FrontendDiagnostic.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/Support/MemoryBuffer.h"
#include "llvm/System/Path.h"
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) {
+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, '=')) {
@@ -34,9 +40,9 @@ static void DefineBuiltinMacro(std::vector<char> &Buf, const char *Macro) {
// Per GCC -D semantics, the macro ends at \n if it exists.
const char *End = strpbrk(Equal, "\n\r");
if (End) {
- fprintf(stderr, "warning: macro '%s' contains embedded newline, text "
- "after the newline is ignored.\n",
- std::string(Macro, Equal).c_str());
+ 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);
}
@@ -118,11 +124,9 @@ static void AddImplicitIncludePTH(std::vector<char> &Buf, Preprocessor &PP,
const char *OriginalFile = P->getOriginalSourceFile();
if (!OriginalFile) {
- assert(!ImplicitIncludePTH.empty());
- fprintf(stderr, "error: PTH file '%s' does not designate an original "
- "source header file for -include-pth\n",
- ImplicitIncludePTH.c_str());
- exit (1);
+ PP.getDiagnostics().Report(diag::err_fe_pth_file_has_no_source_header)
+ << ImplicitIncludePTH;
+ return;
}
AddImplicitInclude(Buf, OriginalFile);
@@ -358,6 +362,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineBuiltinMacro(Buf, "__int16=__INT16_TYPE__");
DefineBuiltinMacro(Buf, "__int32=__INT32_TYPE__");
DefineBuiltinMacro(Buf, "__int64=__INT64_TYPE__");
+ // Both __PRETTY_FUNCTION__ and __FUNCTION__ are GCC extensions, however
+ // VC++ appears to only like __FUNCTION__.
+ DefineBuiltinMacro(Buf, "__PRETTY_FUNCTION__=__FUNCTION__");
// Work around some issues with Visual C++ headerws.
if (LangOpts.CPlusPlus) {
// Since we define wchar_t in C++ mode.
@@ -478,6 +485,52 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
TI.getTargetDefines(LangOpts, Buf);
}
+// Initialize the remapping of files to alternative contents, e.g.,
+// those specified through other files.
+static void InitializeFileRemapping(Diagnostic &Diags,
+ SourceManager &SourceMgr,
+ FileManager &FileMgr,
+ const PreprocessorOptions &InitOpts) {
+ // Remap files in the source manager.
+ for (PreprocessorOptions::remapped_file_iterator
+ Remap = InitOpts.remapped_file_begin(),
+ RemapEnd = InitOpts.remapped_file_end();
+ Remap != RemapEnd;
+ ++Remap) {
+ // Find the file that we're mapping to.
+ const FileEntry *ToFile = FileMgr.getFile(Remap->second);
+ if (!ToFile) {
+ Diags.Report(diag::err_fe_remap_missing_to_file)
+ << Remap->first << Remap->second;
+ continue;
+ }
+
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+ ToFile->getSize(),
+ 0);
+ if (!FromFile) {
+ Diags.Report(diag::err_fe_remap_missing_from_file)
+ << Remap->first;
+ continue;
+ }
+
+ // Load the contents of the file we're mapping to.
+ std::string ErrorStr;
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
+ if (!Buffer) {
+ Diags.Report(diag::err_fe_error_opening)
+ << Remap->second << ErrorStr;
+ continue;
+ }
+
+ // Override the contents of the "from" file with the contents of
+ // the "to" file.
+ SourceMgr.overrideFileContents(FromFile, Buffer);
+ }
+}
+
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file. This returns true on error.
///
@@ -486,6 +539,9 @@ void clang::InitializePreprocessor(Preprocessor &PP,
const HeaderSearchOptions &HSOpts) {
std::vector<char> PredefineBuffer;
+ InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(),
+ PP.getFileManager(), InitOpts);
+
const char *LineDirective = "# 1 \"<built-in>\" 3\n";
PredefineBuffer.insert(PredefineBuffer.end(),
LineDirective, LineDirective+strlen(LineDirective));
@@ -506,7 +562,8 @@ void clang::InitializePreprocessor(Preprocessor &PP,
if (InitOpts.Macros[i].second) // isUndef
UndefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str());
else
- DefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str());
+ DefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str(),
+ &PP.getDiagnostics());
}
// If -imacros are specified, include them now. These are processed before
@@ -523,6 +580,11 @@ void clang::InitializePreprocessor(Preprocessor &PP,
AddImplicitInclude(PredefineBuffer, 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));
+
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
PP.setPredefines(&PredefineBuffer[0]);
diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp
index 771a58c60501..ed0ea1f45ef6 100644
--- a/lib/Frontend/LangStandards.cpp
+++ b/lib/Frontend/LangStandards.cpp
@@ -14,13 +14,13 @@ using namespace clang;
using namespace clang::frontend;
#define LANGSTANDARD(id, name, desc, features) \
- static LangStandard Lang_##id = { name, desc, features };
+ static const LangStandard Lang_##id = { name, desc, features };
#include "clang/Frontend/LangStandards.def"
const LangStandard &LangStandard::getLangStandardForKind(Kind K) {
switch (K) {
default:
- llvm::llvm_unreachable("Invalid language kind!");
+ llvm_unreachable("Invalid language kind!");
case lang_unspecified:
llvm::llvm_report_error("getLangStandardForKind() on unspecified kind");
#define LANGSTANDARD(id, name, desc, features) \
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index cb96bcb48aec..48ef2ac31aba 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -116,6 +116,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
diag::warn_pch_stack_protector);
PARSE_LANGOPT_BENIGN(InstantiationDepth);
PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl);
+ PARSE_LANGOPT_BENIGN(CatchUndefined);
PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors);
#undef PARSE_LANGOPT_IRRELEVANT
#undef PARSE_LANGOPT_BENIGN
@@ -1569,13 +1570,14 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {
/// \brief Retrieve the name of the original source file name
/// directly from the PCH file, without actually loading the PCH
/// file.
-std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
+std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
+ Diagnostic &Diags) {
// Open the PCH file.
std::string ErrStr;
llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
if (!Buffer) {
- fprintf(stderr, "error: %s\n", ErrStr.c_str());
+ Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr;
return std::string();
}
@@ -1591,9 +1593,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
Stream.Read(8) != 'P' ||
Stream.Read(8) != 'C' ||
Stream.Read(8) != 'H') {
- fprintf(stderr,
- "error: '%s' does not appear to be a precompiled header file\n",
- PCHFileName.c_str());
+ Diags.Report(diag::err_fe_not_a_pch_file) << PCHFileName;
return std::string();
}
@@ -1608,14 +1608,14 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
switch (BlockID) {
case pch::PCH_BLOCK_ID:
if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
- fprintf(stderr, "error: malformed block record in PCH file\n");
+ Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
return std::string();
}
break;
default:
if (Stream.SkipBlock()) {
- fprintf(stderr, "error: malformed block record in PCH file\n");
+ Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
return std::string();
}
break;
@@ -1625,7 +1625,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
if (Code == llvm::bitc::END_BLOCK) {
if (Stream.ReadBlockEnd()) {
- fprintf(stderr, "error: error at end of module block in PCH file\n");
+ Diags.Report(diag::err_fe_pch_error_at_end_block) << PCHFileName;
return std::string();
}
continue;
@@ -1720,6 +1720,8 @@ bool PCHReader::ParseLanguageOptions(
++Idx;
PARSE_LANGOPT(InstantiationDepth);
PARSE_LANGOPT(OpenCL);
+ PARSE_LANGOPT(CatchUndefined);
+ // FIXME: Missing ElideConstructors?!
#undef PARSE_LANGOPT
return Listener->ReadLanguageOptions(LangOpts);
@@ -1881,6 +1883,10 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Exceptions.data());
}
+ case pch::TYPE_UNRESOLVED_USING:
+ return Context->getTypeDeclType(
+ cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
+
case pch::TYPE_TYPEDEF:
assert(Record.size() == 1 && "incorrect encoding of typedef type");
return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
@@ -2045,6 +2051,9 @@ void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
@@ -2107,17 +2116,17 @@ void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,
+TypeSourceInfo *PCHReader::GetTypeSourceInfo(const RecordData &Record,
unsigned &Idx) {
QualType InfoTy = GetType(Record[Idx++]);
if (InfoTy.isNull())
return 0;
- DeclaratorInfo *DInfo = getContext()->CreateDeclaratorInfo(InfoTy);
+ TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy);
TypeLocReader TLR(*this, Record, Idx);
- for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
TLR.Visit(TL);
- return DInfo;
+ return TInfo;
}
QualType PCHReader::GetType(pch::TypeID ID) {
@@ -2183,7 +2192,7 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
case TemplateArgument::Expression:
return ReadDeclExpr();
case TemplateArgument::Type:
- return GetDeclaratorInfo(Record, Index);
+ return GetTypeSourceInfo(Record, Index);
case TemplateArgument::Template: {
SourceLocation
QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
@@ -2198,7 +2207,7 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
case TemplateArgument::Pack:
return TemplateArgumentLocInfo();
}
- llvm::llvm_unreachable("unexpected template argument loc");
+ llvm_unreachable("unexpected template argument loc");
return TemplateArgumentLocInfo();
}
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 03f3b4767994..01e1a4191a99 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -107,7 +107,7 @@ void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
// the type associated with the TypedefDecl.
VisitNamedDecl(TD);
uint64_t TypeData = Record[Idx++];
- TD->setTypeDeclaratorInfo(Reader.GetDeclaratorInfo(Record, Idx));
+ TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
TD->setTypeForDecl(Reader.GetType(TypeData).getTypePtr());
}
@@ -126,6 +126,7 @@ void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
VisitTagDecl(ED);
ED->setIntegerType(Reader.GetType(Record[Idx++]));
+ ED->setPromotionType(Reader.GetType(Record[Idx++]));
// FIXME: C++ InstantiatedFrom
}
@@ -150,9 +151,9 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
VisitValueDecl(DD);
- DeclaratorInfo *DInfo = Reader.GetDeclaratorInfo(Record, Idx);
- if (DInfo)
- DD->setDeclaratorInfo(DInfo);
+ TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Record, Idx);
+ if (TInfo)
+ DD->setTypeSourceInfo(TInfo);
}
void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index 00734a0854a4..f28e61e1ecdc 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -349,7 +349,7 @@ unsigned PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
unsigned PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
- E->setDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
// FIXME: read qualifier
// FIXME: read explicit template arguments
@@ -428,7 +428,7 @@ unsigned PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
E->setArgument(cast<Expr>(StmtStack.back()));
++Idx;
} else {
- E->setArgument(Reader.GetDeclaratorInfo(Record, Idx));
+ E->setArgument(Reader.GetTypeSourceInfo(Record, Idx));
}
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -456,7 +456,7 @@ unsigned PCHStmtReader::VisitCallExpr(CallExpr *E) {
unsigned PCHStmtReader::VisitMemberExpr(MemberExpr *E) {
VisitExpr(E);
E->setBase(cast<Expr>(StmtStack.back()));
- E->setMemberDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+ E->setMemberDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
E->setMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setArrow(Record[Idx++]);
return 1;
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e79f9c9dac19..681c1ff32cb0 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -166,6 +166,14 @@ void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
Code = pch::TYPE_FUNCTION_PROTO;
}
+#if 0
+// For when we want it....
+void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+ Writer.AddDeclRef(T->getDecl(), Record);
+ Code = pch::TYPE_UNRESOLVED_USING;
+}
+#endif
+
void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
Code = pch::TYPE_TYPEDEF;
@@ -337,6 +345,9 @@ void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Writer.AddSourceLocation(TL.getNameLoc(), Record);
}
@@ -770,6 +781,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
Record.push_back(LangOpts.getStackProtectorMode());
Record.push_back(LangOpts.InstantiationDepth);
Record.push_back(LangOpts.OpenCL);
+ Record.push_back(LangOpts.CatchUndefined);
Record.push_back(LangOpts.ElideConstructors);
Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record);
}
@@ -2129,7 +2141,7 @@ void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
AddStmt(Arg.getLocInfo().getAsExpr());
break;
case TemplateArgument::Type:
- AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record);
+ AddTypeSourceInfo(Arg.getLocInfo().getAsTypeSourceInfo(), Record);
break;
case TemplateArgument::Template:
Record.push_back(
@@ -2145,15 +2157,15 @@ void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
}
}
-void PCHWriter::AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record) {
- if (DInfo == 0) {
+void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
+ if (TInfo == 0) {
AddTypeRef(QualType(), Record);
return;
}
- AddTypeRef(DInfo->getType(), Record);
+ AddTypeRef(TInfo->getType(), Record);
TypeLocWriter TLW(*this, Record);
- for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
+ for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
TLW.Visit(TL);
}
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index c7bfee2c8bcd..049cdb03ea3b 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -14,9 +14,9 @@
#include "clang/Frontend/PCHWriter.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Bitcode/BitstreamWriter.h"
-#include <cstdio>
-
+#include "llvm/Support/ErrorHandling.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -106,7 +106,7 @@ void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
VisitTypeDecl(D);
- Writer.AddDeclaratorInfo(D->getTypeDeclaratorInfo(), Record);
+ Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
Code = pch::DECL_TYPEDEF;
}
@@ -123,6 +123,7 @@ void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
VisitTagDecl(D);
Writer.AddTypeRef(D->getIntegerType(), Record);
+ Writer.AddTypeRef(D->getPromotionType(), Record);
// FIXME: C++ InstantiatedFrom
Code = pch::DECL_ENUM;
}
@@ -151,7 +152,7 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
VisitValueDecl(D);
- Writer.AddDeclaratorInfo(D->getDeclaratorInfo(), Record);
+ Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
}
void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
@@ -370,7 +371,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
// If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here
// we dynamically check for the properties that we optimize for, but don't
// know are true of all PARM_VAR_DECLs.
- if (!D->getDeclaratorInfo() &&
+ if (!D->getTypeSourceInfo() &&
!D->hasAttrs() &&
!D->isImplicit() &&
!D->isUsed() &&
@@ -568,12 +569,9 @@ void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
W.Visit(D);
if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
- if (!W.Code) {
- fprintf(stderr, "Cannot serialize declaration of kind %s\n",
- D->getDeclKindName());
- assert(false && "Unhandled declaration kind while generating PCH");
- exit(-1);
- }
+ if (!W.Code)
+ llvm::llvm_report_error(llvm::StringRef("unexpected declaration kind '") +
+ D->getDeclKindName() + "'");
Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
// If the declaration had any attributes, write them now.
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp
index 27b83ed6cbb2..22f7ad66d9d1 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Frontend/PCHWriterStmt.cpp
@@ -388,7 +388,7 @@ void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
VisitExpr(E);
Record.push_back(E->isSizeOf());
if (E->isArgumentType())
- Writer.AddDeclaratorInfo(E->getArgumentTypeInfo(), Record);
+ Writer.AddTypeSourceInfo(E->getArgumentTypeInfo(), Record);
else {
Record.push_back(0);
Writer.WriteSubStmt(E->getArgumentExpr());
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
index 80ee2c2e8eba..92cafe6d1cbe 100644
--- a/lib/Frontend/PlistDiagnostics.cpp
+++ b/lib/Frontend/PlistDiagnostics.cpp
@@ -30,6 +30,40 @@ namespace clang {
}
namespace {
+struct CompareDiagnostics {
+ // Compare if 'X' is "<" than 'Y'.
+ bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
+ // First compare by location
+ const FullSourceLoc &XLoc = X->getLocation().asLocation();
+ const FullSourceLoc &YLoc = Y->getLocation().asLocation();
+ if (XLoc < YLoc)
+ return true;
+ if (XLoc != YLoc)
+ return false;
+
+ // Next, compare by bug type.
+ llvm::StringRef XBugType = X->getBugType();
+ llvm::StringRef YBugType = Y->getBugType();
+ if (XBugType < YBugType)
+ return true;
+ if (XBugType != YBugType)
+ return false;
+
+ // Next, compare by bug description.
+ llvm::StringRef XDesc = X->getDescription();
+ llvm::StringRef YDesc = Y->getDescription();
+ if (XDesc < YDesc)
+ return true;
+ if (XDesc != YDesc)
+ return false;
+
+ // FIXME: Further refine by comparing PathDiagnosticPieces?
+ return false;
+ }
+};
+}
+
+namespace {
class PlistDiagnostics : public PathDiagnosticClient {
std::vector<const PathDiagnostic*> BatchedDiags;
const std::string OutputFile;
@@ -314,6 +348,11 @@ void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
return;
flushed = true;
+
+ // Sort the diagnostics so that they are always emitted in a deterministic
+ // order.
+ if (!BatchedDiags.empty())
+ std::sort(BatchedDiags.begin(), BatchedDiags.end(), CompareDiagnostics());
// Build up a set of FIDs that we use by scanning the locations and
// ranges of the diagnostics.
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 37424057809c..d9708d8bced4 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -36,22 +36,23 @@ static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
if (MI.isFunctionLike()) {
OS << '(';
- if (MI.arg_empty())
- ;
- else if (MI.getNumArgs() == 1)
- OS << (*MI.arg_begin())->getName();
- else {
+ if (!MI.arg_empty()) {
MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
- OS << (*AI++)->getName();
- while (AI != E)
- OS << ',' << (*AI++)->getName();
- }
-
- if (MI.isVariadic()) {
- if (!MI.arg_empty())
+ for (; AI+1 != E; ++AI) {
+ OS << (*AI)->getName();
OS << ',';
- OS << "...";
+ }
+
+ // Last argument.
+ if ((*AI)->getName() == "__VA_ARGS__")
+ OS << "...";
+ else
+ OS << (*AI)->getName();
}
+
+ if (MI.isGNUVarargs())
+ OS << "..."; // #define foo(x...)
+
OS << ')';
}
@@ -94,6 +95,7 @@ private:
bool Initialized;
bool DisableLineMarkers;
bool DumpDefines;
+ bool UseLineDirective;
public:
PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os,
bool lineMarkers, bool defines)
@@ -105,6 +107,9 @@ public:
EmittedMacroOnThisLine = false;
FileType = SrcMgr::C_User;
Initialized = false;
+
+ // If we're in microsoft mode, use normal #line instead of line markers.
+ UseLineDirective = PP.getLangOptions().Microsoft;
}
void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
@@ -141,17 +146,24 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
EmittedMacroOnThisLine = false;
}
- OS << '#' << ' ' << LineNo << ' ' << '"';
- OS.write(&CurFilename[0], CurFilename.size());
- OS << '"';
-
- if (ExtraLen)
- OS.write(Extra, ExtraLen);
-
- if (FileType == SrcMgr::C_System)
- OS.write(" 3", 2);
- else if (FileType == SrcMgr::C_ExternCSystem)
- OS.write(" 3 4", 4);
+ // Emit #line directives or GNU line markers depending on what mode we're in.
+ if (UseLineDirective) {
+ OS << "#line" << ' ' << LineNo << ' ' << '"';
+ OS.write(&CurFilename[0], CurFilename.size());
+ OS << '"';
+ } else {
+ OS << '#' << ' ' << LineNo << ' ' << '"';
+ OS.write(&CurFilename[0], CurFilename.size());
+ OS << '"';
+
+ if (ExtraLen)
+ OS.write(Extra, ExtraLen);
+
+ if (FileType == SrcMgr::C_System)
+ OS.write(" 3", 2);
+ else if (FileType == SrcMgr::C_ExternCSystem)
+ OS.write(" 3 4", 4);
+ }
OS << '\n';
}
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 710fa55b69bf..df85c13cea78 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -255,7 +255,10 @@ namespace {
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
- void WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S);
+ void WarnAboutReturnGotoStmts(Stmt *S);
+ void HasReturnStmts(Stmt *S, bool &hasReturns);
+ void RewriteTryReturnStmts(Stmt *S);
+ void RewriteSyncReturnStmts(Stmt *S, std::string buf);
Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
@@ -328,11 +331,16 @@ namespace {
const char *funcName, std::string Tag);
std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
const char *funcName, std::string Tag);
- std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
- bool hasCopyDisposeHelpers);
+ std::string SynthesizeBlockImpl(BlockExpr *CE,
+ std::string Tag, std::string Desc);
+ std::string SynthesizeBlockDescriptor(std::string DescTag,
+ std::string ImplTag,
+ int i, const char *funcName,
+ unsigned hasCopy);
Stmt *SynthesizeBlockCall(CallExpr *Exp);
void SynthesizeBlockLiterals(SourceLocation FunLocStart,
const char *FunName);
+ void RewriteRecordBody(RecordDecl *RD);
void CollectBlockDeclRefInfo(BlockExpr *Exp);
void GetBlockCallExprs(Stmt *S);
@@ -547,14 +555,21 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "struct __block_impl {\n";
Preamble += " void *isa;\n";
Preamble += " int Flags;\n";
- Preamble += " int Size;\n";
+ Preamble += " int Reserved;\n";
Preamble += " void *FuncPtr;\n";
Preamble += "};\n";
Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
- Preamble += "__OBJC_RW_STATICIMPORT void _Block_object_assign(void *, const void *, const int);\n";
- Preamble += "__OBJC_RW_STATICIMPORT void _Block_object_dispose(const void *, const int);\n";
- Preamble += "__OBJC_RW_STATICIMPORT void *_NSConcreteGlobalBlock[32];\n";
- Preamble += "__OBJC_RW_STATICIMPORT void *_NSConcreteStackBlock[32];\n";
+ Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
+ Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_assign(void *, const void *, const int);\n";
+ Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
+ 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 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";
Preamble += "#endif\n";
if (LangOpts.Microsoft) {
Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
@@ -1325,7 +1340,12 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
// type elem;
NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
QualType ElementType = cast<ValueDecl>(D)->getType();
- elementTypeAsString = ElementType.getAsString();
+ if (ElementType->isObjCQualifiedIdType() ||
+ ElementType->isObjCQualifiedInterfaceType())
+ // Simply use 'id' for all qualified types.
+ elementTypeAsString = "id";
+ else
+ elementTypeAsString = ElementType.getAsString();
buf += elementTypeAsString;
buf += " ";
elementName = D->getNameAsCString();
@@ -1335,8 +1355,13 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
else {
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
elementName = DR->getDecl()->getNameAsCString();
- elementTypeAsString
- = cast<ValueDecl>(DR->getDecl())->getType().getAsString();
+ ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
+ if (VD->getType()->isObjCQualifiedIdType() ||
+ VD->getType()->isObjCQualifiedInterfaceType())
+ // Simply use 'id' for all qualified types.
+ elementTypeAsString = "id";
+ else
+ elementTypeAsString = VD->getType().getAsString();
}
// struct __objcFastEnumerationState enumState = { 0 };
@@ -1502,7 +1527,9 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
buf += "}\n";
buf += "{ /* implicit finally clause */\n";
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
- buf += " objc_sync_exit(";
+
+ std::string syncBuf;
+ syncBuf += " objc_sync_exit(";
Expr *syncExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(),
CastExpr::CK_Unknown,
S->getSynchExpr(),
@@ -1513,31 +1540,102 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
syncExpr->printPretty(syncExprBuf, *Context, 0,
PrintingPolicy(LangOpts));
- buf += syncExprBuf.str();
- buf += ");\n";
- buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
+ syncBuf += syncExprBuf.str();
+ syncBuf += ");";
+
+ buf += syncBuf;
+ buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
buf += "}\n";
buf += "}";
ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
+
+ bool hasReturns = false;
+ HasReturnStmts(S->getSynchBody(), hasReturns);
+ if (hasReturns)
+ RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
+
return 0;
}
-void RewriteObjC::WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S) {
+void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
+{
// Perform a bottom up traversal of all children.
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
CI != E; ++CI)
if (*CI)
- WarnAboutReturnGotoContinueOrBreakStmts(*CI);
+ WarnAboutReturnGotoStmts(*CI);
- if (isa<ReturnStmt>(S) || isa<ContinueStmt>(S) ||
- isa<BreakStmt>(S) || isa<GotoStmt>(S)) {
+ if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
Diags.Report(Context->getFullLoc(S->getLocStart()),
TryFinallyContainsReturnDiag);
}
return;
}
+void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
+{
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+ CI != E; ++CI)
+ if (*CI)
+ HasReturnStmts(*CI, hasReturns);
+
+ if (isa<ReturnStmt>(S))
+ hasReturns = true;
+ return;
+}
+
+void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+ CI != E; ++CI)
+ if (*CI) {
+ RewriteTryReturnStmts(*CI);
+ }
+ if (isa<ReturnStmt>(S)) {
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
+ SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+ std::string buf;
+ buf = "{ objc_exception_try_exit(&_stack); return";
+
+ ReplaceText(startLoc, 6, buf.c_str(), buf.size());
+ InsertText(onePastSemiLoc, "}", 1);
+ }
+ return;
+}
+
+void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+ CI != E; ++CI)
+ if (*CI) {
+ RewriteSyncReturnStmts(*CI, syncExitBuf);
+ }
+ if (isa<ReturnStmt>(S)) {
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
+ SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+ std::string buf;
+ buf = "{ objc_exception_try_exit(&_stack);";
+ buf += syncExitBuf;
+ buf += " return";
+
+ ReplaceText(startLoc, 6, buf.c_str(), buf.size());
+ InsertText(onePastSemiLoc, "}", 1);
+ }
+ return;
+}
+
Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
// Get the start location and compute the semi location.
SourceLocation startLoc = S->getLocStart();
@@ -1689,13 +1787,21 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
lastCurlyLoc = body->getLocEnd();
// Now check for any return/continue/go statements within the @try.
- WarnAboutReturnGotoContinueOrBreakStmts(S->getTryBody());
+ WarnAboutReturnGotoStmts(S->getTryBody());
} else { /* no finally clause - make sure we synthesize an implicit one */
buf = "{ /* implicit finally clause */\n";
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
buf += "}";
ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
+
+ // Now check for any return/continue/go statements within the @try.
+ // The implicit finally clause won't called if the @try contains any
+ // jump statements.
+ bool hasReturns = false;
+ HasReturnStmts(S->getTryBody(), hasReturns);
+ if (hasReturns)
+ RewriteTryReturnStmts(S->getTryBody());
}
// Now emit the final closing curly brace...
lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
@@ -1878,6 +1984,10 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
return;
Type = proto->getResultType();
}
+ else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
+ Loc = FD->getLocation();
+ Type = FD->getType();
+ }
else
return;
@@ -2134,8 +2244,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
PrintingPolicy(LangOpts));
Preamble += prettyBuf.str();
Preamble += ",";
- // The minus 2 removes the begin/end double quotes.
- Preamble += utostr(prettyBuf.str().size()-2) + "};\n";
+ Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
&Context->Idents.get(S.c_str()), strType, 0,
@@ -2569,7 +2678,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// Build sizeof(returnType)
SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
- Context->getTrivialDeclaratorInfo(returnType),
+ Context->getTrivialTypeSourceInfo(returnType),
Context->getSizeType(),
SourceLocation(), SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
@@ -2609,12 +2718,12 @@ Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
// typedef struct objc_object Protocol;
QualType RewriteObjC::getProtocolType() {
if (!ProtocolTypeDecl) {
- DeclaratorInfo *DInfo
- = Context->getTrivialDeclaratorInfo(Context->getObjCIdType());
+ TypeSourceInfo *TInfo
+ = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
SourceLocation(),
&Context->Idents.get("Protocol"),
- DInfo);
+ TInfo);
}
return Context->getTypeDeclType(ProtocolTypeDecl);
}
@@ -2737,7 +2846,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size());
} else {
// rewrite the original header *without* disturbing the '{'
- ReplaceText(LocStart, cursor-startBuf-1, Result.c_str(), Result.size());
+ ReplaceText(LocStart, cursor-startBuf, Result.c_str(), Result.size());
}
if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
Result = "\n struct ";
@@ -3689,20 +3798,18 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
return S;
}
-std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
- bool hasCopyDisposeHelpers) {
+std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
+ std::string Desc) {
std::string S = "\nstruct " + Tag;
std::string Constructor = " " + Tag;
S += " {\n struct __block_impl impl;\n";
+ S += " struct " + Desc;
+ S += "* Desc;\n";
- if (hasCopyDisposeHelpers)
- S += " void *copy;\n void *dispose;\n";
-
- Constructor += "(void *fp";
-
- if (hasCopyDisposeHelpers)
- Constructor += ", void *copyHelp, void *disposeHelp";
+ Constructor += "(void *fp, "; // Invoke function pointer.
+ Constructor += "struct " + Desc; // Descriptor pointer.
+ Constructor += " *desc";
if (BlockDeclRefs.size()) {
// Output all "by copy" declarations.
@@ -3765,11 +3872,9 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
else
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
- Constructor += " impl.Size = sizeof(";
- Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
+ Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
- if (hasCopyDisposeHelpers)
- Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
+ Constructor += " Desc = desc;\n";
// Initialize all "by copy" arguments.
for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
@@ -3800,10 +3905,8 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
else
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
- Constructor += " impl.Size = sizeof(";
- Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
- if (hasCopyDisposeHelpers)
- Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
+ Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
+ Constructor += " Desc = desc;\n";
}
Constructor += " ";
Constructor += "}\n";
@@ -3812,6 +3915,29 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
return S;
}
+std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
+ std::string ImplTag, int i,
+ const char *FunName,
+ unsigned hasCopy) {
+ std::string S = "\nstatic struct " + DescTag;
+
+ S += " {\n unsigned long reserved;\n";
+ S += " unsigned long Block_size;\n";
+ if (hasCopy) {
+ S += " void *copy;\n void *dispose;\n";
+ }
+ S += "} ";
+
+ S += DescTag + "_DATA = { 0, sizeof(struct ";
+ S += ImplTag + ")";
+ if (hasCopy) {
+ S += ", __" + std::string(FunName) + "_block_copy_" + utostr(i);
+ S += ", __" + std::string(FunName) + "_block_dispose_" + utostr(i);
+ }
+ S += "};\n";
+ return S;
+}
+
void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
const char *FunName) {
// Insert closures that were part of the function.
@@ -3819,21 +3945,24 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
CollectBlockDeclRefInfo(Blocks[i]);
- std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
+ std::string ImplTag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
+ std::string DescTag = "__" + std::string(FunName) + "_block_desc_" + utostr(i);
- std::string CI = SynthesizeBlockImpl(Blocks[i], Tag,
- ImportedBlockDecls.size() > 0);
+ std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
InsertText(FunLocStart, CI.c_str(), CI.size());
- std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
+ std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
InsertText(FunLocStart, CF.c_str(), CF.size());
if (ImportedBlockDecls.size()) {
- std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
+ std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
InsertText(FunLocStart, HF.c_str(), HF.size());
}
+ std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
+ ImportedBlockDecls.size() > 0);
+ InsertText(FunLocStart, BD.c_str(), BD.size());
BlockDeclRefs.clear();
BlockByRefDecls.clear();
@@ -4243,25 +4372,21 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
SourceLocation());
InitExprs.push_back(castExpr);
- if (ImportedBlockDecls.size()) {
- std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber;
- FD = SynthBlockInitFunctionDecl(Buf.c_str());
- Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
- castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg,
- Context->VoidPtrTy, SourceLocation(),
- SourceLocation());
- InitExprs.push_back(castExpr);
-
- Buf = "__" + FuncName + "_block_dispose_" + BlockNumber;
- FD = SynthBlockInitFunctionDecl(Buf.c_str());
- Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
- castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg,
- Context->VoidPtrTy, SourceLocation(),
- SourceLocation());
- InitExprs.push_back(castExpr);
- }
+ // Initialize the block descriptor.
+ std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
+
+ VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
+ &Context->Idents.get(DescData.c_str()),
+ Context->VoidPtrTy, 0,
+ VarDecl::Static);
+ UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
+ new (Context) DeclRefExpr(NewVD,
+ Context->VoidPtrTy, SourceLocation()),
+ UnaryOperator::AddrOf,
+ Context->getPointerType(Context->VoidPtrTy),
+ SourceLocation());
+ InitExprs.push_back(DescRefExpr);
+
// Add initializers for any closure decl refs.
if (BlockDeclRefs.size()) {
Expr *Exp;
@@ -4297,6 +4422,17 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
InitExprs.push_back(Exp);
}
}
+ if (ImportedBlockDecls.size()) { // generate "1<<25" to indicate we have helper functions.
+ unsigned IntSize =
+ static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+ BinaryOperator *Exp = new (Context) BinaryOperator(
+ new (Context) IntegerLiteral(llvm::APInt(IntSize, 1),
+ Context->IntTy,SourceLocation()),
+ new (Context) IntegerLiteral(llvm::APInt(IntSize, 25),
+ Context->IntTy, SourceLocation()),
+ BinaryOperator::Shl, Context->IntTy, SourceLocation());
+ InitExprs.push_back(Exp);
+ }
NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
FType, SourceLocation());
NewRep = new (Context) UnaryOperator(NewRep, UnaryOperator::AddrOf,
@@ -4486,7 +4622,14 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// FIXME: What we're doing here is modifying the type-specifier that
// precedes the first Decl. In the future the DeclGroup should have
// a separate type-specifier that we can rewrite.
- RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
+ // NOTE: We need to avoid rewriting the DeclStmt if it is within
+ // the context of an ObjCForCollectionStmt. For example:
+ // NSArray *someArray;
+ // for (id <FooProtocol> index in someArray) ;
+ // This is because RewriteObjCForCollectionStmt() does textual rewriting
+ // and it depends on the original text locations/positions.
+ if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+ RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
// Blocks rewrite rules.
for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
@@ -4552,6 +4695,18 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
return S;
}
+void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
+ for (RecordDecl::field_iterator i = RD->field_begin(),
+ e = RD->field_end(); i != e; ++i) {
+ FieldDecl *FD = *i;
+ if (isTopLevelBlockPointerType(FD->getType()))
+ RewriteBlockPointerDecl(FD);
+ if (FD->getType()->isObjCQualifiedIdType() ||
+ FD->getType()->isObjCQualifiedInterfaceType())
+ RewriteObjCQualifiedInterfaceTypes(FD);
+ }
+}
+
/// HandleDeclInMainFile - This is called for each top-level decl defined in the
/// main file of the input.
void RewriteObjC::HandleDeclInMainFile(Decl *D) {
@@ -4618,6 +4773,10 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
RewriteCastExpr(CE);
}
}
+ } else if (VD->getType()->isRecordType()) {
+ RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
}
if (VD->getInit()) {
GlobalVarDecl = VD;
@@ -4645,17 +4804,16 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
RewriteBlockPointerDecl(TD);
else if (TD->getUnderlyingType()->isFunctionPointerType())
CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+ else if (TD->getUnderlyingType()->isRecordType()) {
+ RecordDecl *RD = TD->getUnderlyingType()->getAs<RecordType>()->getDecl();
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
+ }
return;
}
if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
- if (RD->isDefinition()) {
- for (RecordDecl::field_iterator i = RD->field_begin(),
- e = RD->field_end(); i != e; ++i) {
- FieldDecl *FD = *i;
- if (isTopLevelBlockPointerType(FD->getType()))
- RewriteBlockPointerDecl(FD);
- }
- }
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
return;
}
// Nothing yet.
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 6ab0e1605276..61f8a70fffff 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -279,13 +279,14 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
assert(!Loc.isInvalid() && "must have a valid source location here");
// If this is a macro ID, first emit information about where this was
- // instantiated (recursively) then emit information about where. the token was
+ // instantiated (recursively) then emit information about where the token was
// spelled from.
if (!Loc.isFileID()) {
SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
// FIXME: Map ranges?
EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns);
+ // Map the location.
Loc = SM.getImmediateSpellingLoc(Loc);
// Map the ranges.
@@ -295,15 +296,22 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
if (E.isMacroID()) E = SM.getImmediateSpellingLoc(E);
Ranges[i] = SourceRange(S, E);
}
+
+ // Get the pretty name, according to #line directives etc.
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+
+ // If this diagnostic is not in the main file, print out the "included from"
+ // lines.
+ if (LastWarningLoc != PLoc.getIncludeLoc()) {
+ LastWarningLoc = PLoc.getIncludeLoc();
+ PrintIncludeStack(LastWarningLoc, SM);
+ }
if (DiagOpts->ShowLocation) {
- std::pair<FileID, unsigned> IInfo = SM.getDecomposedInstantiationLoc(Loc);
-
// Emit the file/line/column that this expansion came from.
- OS << SM.getBuffer(IInfo.first)->getBufferIdentifier() << ':'
- << SM.getLineNumber(IInfo.first, IInfo.second) << ':';
+ OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':';
if (DiagOpts->ShowColumn)
- OS << SM.getColumnNumber(IInfo.first, IInfo.second) << ':';
+ OS << PLoc.getColumn() << ':';
OS << ' ';
}
OS << "note: instantiated from:\n";
@@ -489,12 +497,17 @@ static inline char findMatchingPunctuation(char c) {
///
/// \returns the index pointing one character past the end of the
/// word.
-unsigned findEndOfWord(unsigned Start,
- const llvm::SmallVectorImpl<char> &Str,
- unsigned Length, unsigned Column,
- unsigned Columns) {
+static unsigned findEndOfWord(unsigned Start,
+ const llvm::SmallVectorImpl<char> &Str,
+ unsigned Length, unsigned Column,
+ unsigned Columns) {
+ assert(Start < Str.size() && "Invalid start position!");
unsigned End = Start + 1;
+ // If we are already at the end of the string, take that as the word.
+ if (End == Str.size())
+ return End;
+
// Determine if the start of the string is actually opening
// punctuation, e.g., a quote or parentheses.
char EndPunct = findMatchingPunctuation(Str[Start]);
@@ -645,11 +658,17 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
if (DiagOpts->ShowLocation) {
if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true);
- OS << PLoc.getFilename() << ':' << LineNo << ':';
- if (DiagOpts->ShowColumn)
- if (unsigned ColNo = PLoc.getColumn())
- OS << ColNo << ':';
-
+
+ // Emit a Visual Studio compatible line number syntax.
+ if (LangOpts && LangOpts->Microsoft) {
+ OS << PLoc.getFilename() << '(' << LineNo << ')';
+ OS << " : ";
+ } else {
+ OS << PLoc.getFilename() << ':' << LineNo << ':';
+ if (DiagOpts->ShowColumn)
+ if (unsigned ColNo = PLoc.getColumn())
+ OS << ColNo << ':';
+ }
if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) {
FileID CaretFileID =
SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));