aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-18 14:59:57 +0000
commitb3d5a323a5ca92ea73443499cee2f15db1ff0fb3 (patch)
tree60a1694bec5a44d15456acc880cb2f91619f66aa /lib/Frontend
parent8f57cb0305232cb53fff00ef151ca716766f3437 (diff)
downloadsrc-b3d5a323a5ca92ea73443499cee2f15db1ff0fb3.tar.gz
src-b3d5a323a5ca92ea73443499cee2f15db1ff0fb3.zip
Update clang to r89205.
Notes
Notes: svn path=/vendor/clang/dist/; revision=199482
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTUnit.cpp16
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp283
-rw-r--r--lib/Frontend/Backend.cpp91
-rw-r--r--lib/Frontend/CMakeLists.txt7
-rw-r--r--lib/Frontend/CompilerInstance.cpp403
-rw-r--r--lib/Frontend/CompilerInvocation.cpp548
-rw-r--r--lib/Frontend/DependencyFile.cpp44
-rw-r--r--lib/Frontend/DocumentXML.cpp4
-rw-r--r--lib/Frontend/FrontendAction.cpp225
-rw-r--r--lib/Frontend/FrontendActions.cpp281
-rw-r--r--lib/Frontend/FrontendOptions.cpp31
-rw-r--r--lib/Frontend/HTMLDiagnostics.cpp2
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp289
-rw-r--r--lib/Frontend/InitPreprocessor.cpp117
-rw-r--r--lib/Frontend/ManagerRegistry.cpp20
-rw-r--r--lib/Frontend/PCHReader.cpp186
-rw-r--r--lib/Frontend/PCHReaderDecl.cpp9
-rw-r--r--lib/Frontend/PCHWriter.cpp22
-rw-r--r--lib/Frontend/PCHWriterDecl.cpp4
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp10
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp3
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp26
-rw-r--r--lib/Frontend/RewriteObjC.cpp2
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp11
-rw-r--r--lib/Frontend/VerifyDiagnosticsClient.cpp344
-rw-r--r--lib/Frontend/Warnings.cpp18
26 files changed, 2498 insertions, 498 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index c0415bf550f8..e3cd6ddd08d6 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Compiler.h"
@@ -61,14 +62,14 @@ public:
return false;
}
- virtual bool ReadTargetTriple(const std::string &Triple) {
+ virtual bool ReadTargetTriple(llvm::StringRef Triple) {
TargetTriple = Triple;
return false;
}
- virtual bool ReadPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+ virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID,
+ llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
Predefines = PCHPredef;
return false;
@@ -132,7 +133,14 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
// PCH loaded successfully. Now create the preprocessor.
// Get information about the target being compiled for.
- AST->Target.reset(TargetInfo::CreateTargetInfo(TargetTriple));
+ //
+ // FIXME: This is broken, we should store the TargetOptions in the PCH.
+ TargetOptions TargetOpts;
+ TargetOpts.ABI = "";
+ 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->getSourceManager(), HeaderInfo));
Preprocessor &PP = *AST->PP.get();
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index d2831fae566a..ede3d474c848 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -20,6 +20,7 @@
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/LocalCheckers.h"
+#include "clang/Analysis/ManagerRegistry.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/AnalysisManager.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
@@ -27,7 +28,6 @@
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Frontend/ManagerRegistry.h"
#include "clang/Frontend/PathDiagnosticClients.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/Compiler.h"
@@ -44,10 +44,6 @@ static ExplodedNode::Auditor* CreateUbiViz();
// Basic type definitions.
//===----------------------------------------------------------------------===//
-namespace {
- typedef void (*CodeAction)(AnalysisManager& Mgr, Decl *D);
-} // end anonymous namespace
-
//===----------------------------------------------------------------------===//
// Special PathDiagnosticClients.
//===----------------------------------------------------------------------===//
@@ -66,116 +62,135 @@ CreatePlistHTMLDiagnosticClient(const std::string& prefix,
namespace {
- class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
- typedef std::vector<CodeAction> Actions;
- Actions FunctionActions;
- Actions ObjCMethodActions;
- Actions ObjCImplementationActions;
- Actions TranslationUnitActions;
+ class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
+ public:
+ typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
+
+ private:
+ typedef std::vector<CodeAction> Actions;
+ Actions FunctionActions;
+ Actions ObjCMethodActions;
+ Actions ObjCImplementationActions;
+ Actions TranslationUnitActions;
- public:
- ASTContext* Ctx;
- const Preprocessor &PP;
- const std::string OutDir;
- AnalyzerOptions Opts;
+public:
+ ASTContext* Ctx;
+ const Preprocessor &PP;
+ const std::string OutDir;
+ AnalyzerOptions Opts;
+ bool declDisplayed;
- // PD is owned by AnalysisManager.
- PathDiagnosticClient *PD;
+ // PD is owned by AnalysisManager.
+ PathDiagnosticClient *PD;
- StoreManagerCreator CreateStoreMgr;
- ConstraintManagerCreator CreateConstraintMgr;
+ StoreManagerCreator CreateStoreMgr;
+ ConstraintManagerCreator CreateConstraintMgr;
- llvm::OwningPtr<AnalysisManager> Mgr;
+ llvm::OwningPtr<AnalysisManager> Mgr;
- AnalysisConsumer(const Preprocessor& pp,
- const std::string& outdir,
- const AnalyzerOptions& opts)
- : Ctx(0), PP(pp), OutDir(outdir),
- Opts(opts), PD(0) {
- DigestAnalyzerOptions();
- }
+ AnalysisConsumer(const Preprocessor& pp,
+ const std::string& outdir,
+ const AnalyzerOptions& opts)
+ : Ctx(0), PP(pp), OutDir(outdir),
+ Opts(opts), declDisplayed(false), PD(0) {
+ DigestAnalyzerOptions();
+ }
- void DigestAnalyzerOptions() {
- // Create the PathDiagnosticClient.
- if (!OutDir.empty()) {
- switch (Opts.AnalysisDiagOpt) {
- default:
+ void DigestAnalyzerOptions() {
+ // Create the PathDiagnosticClient.
+ if (!OutDir.empty()) {
+ switch (Opts.AnalysisDiagOpt) {
+ default:
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
- case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
+ case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
#include "clang/Frontend/Analyses.def"
- }
}
+ }
- // Create the analyzer component creators.
- if (ManagerRegistry::StoreMgrCreator != 0) {
- CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
- }
- else {
- switch (Opts.AnalysisStoreOpt) {
- default:
- assert(0 && "Unknown store manager.");
+ // Create the analyzer component creators.
+ if (ManagerRegistry::StoreMgrCreator != 0) {
+ CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
+ }
+ else {
+ switch (Opts.AnalysisStoreOpt) {
+ default:
+ assert(0 && "Unknown store manager.");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
- case NAME##Model: CreateStoreMgr = CREATEFN; break;
+ case NAME##Model: CreateStoreMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
- }
}
+ }
- if (ManagerRegistry::ConstraintMgrCreator != 0)
- CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
- else {
- switch (Opts.AnalysisConstraintsOpt) {
- default:
- assert(0 && "Unknown store manager.");
+ if (ManagerRegistry::ConstraintMgrCreator != 0)
+ CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
+ else {
+ switch (Opts.AnalysisConstraintsOpt) {
+ default:
+ assert(0 && "Unknown store manager.");
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
- case NAME##Model: CreateConstraintMgr = CREATEFN; break;
+ case NAME##Model: CreateConstraintMgr = CREATEFN; break;
#include "clang/Frontend/Analyses.def"
- }
}
}
-
- void addCodeAction(CodeAction action) {
- FunctionActions.push_back(action);
- ObjCMethodActions.push_back(action);
- }
-
- void addObjCImplementationAction(CodeAction action) {
- ObjCImplementationActions.push_back(action);
- }
-
- void addTranslationUnitAction(CodeAction action) {
- TranslationUnitActions.push_back(action);
+ }
+
+ void DisplayFunction(const Decl *D) {
+ if (!Opts.AnalyzerDisplayProgress || declDisplayed)
+ return;
+
+ declDisplayed = true;
+ // FIXME: Is getCodeDecl() always a named decl?
+ 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';
}
+ }
- virtual void Initialize(ASTContext &Context) {
- Ctx = &Context;
- Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
- PP.getLangOptions(), PD,
- CreateStoreMgr, CreateConstraintMgr,
- Opts.AnalyzerDisplayProgress,
- Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
- Opts.PurgeDead, Opts.EagerlyAssume,
- Opts.TrimGraph));
- }
+ void addCodeAction(CodeAction action) {
+ FunctionActions.push_back(action);
+ ObjCMethodActions.push_back(action);
+ }
- virtual void HandleTopLevelDecl(DeclGroupRef D) {
- for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
- HandleTopLevelSingleDecl(*I);
- }
+ void addObjCImplementationAction(CodeAction action) {
+ ObjCImplementationActions.push_back(action);
+ }
- void HandleTopLevelSingleDecl(Decl *D);
- virtual void HandleTranslationUnit(ASTContext &C);
+ void addTranslationUnitAction(CodeAction action) {
+ TranslationUnitActions.push_back(action);
+ }
- void HandleCode(Decl* D, Stmt* Body, Actions& actions);
- };
+ virtual void Initialize(ASTContext &Context) {
+ Ctx = &Context;
+ Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
+ PP.getLangOptions(), PD,
+ CreateStoreMgr, CreateConstraintMgr,
+ Opts.AnalyzerDisplayProgress,
+ Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
+ Opts.PurgeDead, Opts.EagerlyAssume,
+ Opts.TrimGraph));
+ }
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ declDisplayed = false;
+ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
+ HandleTopLevelSingleDecl(*I);
+ }
+ void HandleTopLevelSingleDecl(Decl *D);
+ virtual void HandleTranslationUnit(ASTContext &C);
+ void HandleCode(Decl* D, Stmt* Body, Actions& actions);
+};
} // end anonymous namespace
namespace llvm {
- template <> struct FoldingSetTrait<CodeAction> {
- static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
+ template <> struct FoldingSetTrait<AnalysisConsumer::CodeAction> {
+ static inline void Profile(AnalysisConsumer::CodeAction X,
+ FoldingSetNodeID& ID) {
ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
}
};
@@ -238,7 +253,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
for (Actions::iterator I = TranslationUnitActions.begin(),
E = TranslationUnitActions.end(); I != E; ++I)
- (*I)(*Mgr, FD);
+ (*I)(*this, *Mgr, FD);
}
if (!ObjCImplementationActions.empty()) {
@@ -272,34 +287,38 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Dispatch on the actions.
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
- (*I)(*Mgr, D);
+ (*I)(*this, *Mgr, D);
}
//===----------------------------------------------------------------------===//
// Analyses
//===----------------------------------------------------------------------===//
-static void ActionWarnDeadStores(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
if (LiveVariables *L = mgr.getLiveVariables(D)) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
}
}
-static void ActionWarnUninitVals(AnalysisManager& mgr, Decl *D) {
- if (CFG* c = mgr.getCFG(D))
+static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+ if (CFG* c = mgr.getCFG(D)) {
+ C.DisplayFunction(D);
CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
+ }
}
-static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
+static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D,
GRTransferFuncs* tf) {
-
llvm::OwningPtr<GRTransferFuncs> TF(tf);
// Display progress.
- mgr.DisplayFunction(D);
+ C.DisplayFunction(D);
// Construct the analysis engine. We first query for the LiveVariables
// information to see if the CFG is valid.
@@ -312,8 +331,14 @@ static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
Eng.setTransferFunctions(tf);
Eng.RegisterInternalChecks(); // FIXME: Internal checks should just
// automatically register.
+
+ if (C.Opts.EnableExperimentalInternalChecks)
+ RegisterExperimentalInternalChecks(Eng);
+
RegisterAppleChecks(Eng, *D);
-
+
+ if (C.Opts.EnableExperimentalChecks)
+ RegisterExperimentalChecks(Eng);
// Set the graph auditor.
llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
@@ -337,85 +362,103 @@ static void ActionGRExprEngine(AnalysisManager& mgr, Decl *D,
Eng.getBugReporter().FlushReports();
}
-static void ActionCheckerCFRefAux(AnalysisManager& mgr, Decl *D,
- bool GCEnabled) {
+static void ActionCheckerCFRefAux(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D, bool GCEnabled) {
GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
GCEnabled,
mgr.getLangOptions());
- ActionGRExprEngine(mgr, D, TF);
+ ActionGRExprEngine(C, mgr, D, TF);
}
-static void ActionCheckerCFRef(AnalysisManager& mgr, Decl *D) {
+static void ActionCheckerCFRef(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
switch (mgr.getLangOptions().getGCMode()) {
default:
assert (false && "Invalid GC mode.");
case LangOptions::NonGC:
- ActionCheckerCFRefAux(mgr, D, false);
+ ActionCheckerCFRefAux(C, mgr, D, false);
break;
case LangOptions::GCOnly:
- ActionCheckerCFRefAux(mgr, D, true);
+ ActionCheckerCFRefAux(C, mgr, D, true);
break;
case LangOptions::HybridGC:
- ActionCheckerCFRefAux(mgr, D, false);
- ActionCheckerCFRefAux(mgr, D, true);
+ ActionCheckerCFRefAux(C, mgr, D, false);
+ ActionCheckerCFRefAux(C, mgr, D, true);
break;
}
}
-static void ActionDisplayLiveVariables(AnalysisManager& mgr, Decl *D) {
+static void ActionDisplayLiveVariables(AnalysisConsumer &C,
+ AnalysisManager& mgr, Decl *D) {
if (LiveVariables* L = mgr.getLiveVariables(D)) {
- mgr.DisplayFunction(D);
+ C.DisplayFunction(D);
L->dumpBlockLiveness(mgr.getSourceManager());
}
}
-static void ActionCFGDump(AnalysisManager& mgr, Decl *D) {
- if (CFG* c = mgr.getCFG(D)) {
- mgr.DisplayFunction(D);
- c->dump(mgr.getLangOptions());
+static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
+ if (CFG *cfg = mgr.getCFG(D)) {
+ C.DisplayFunction(D);
+ cfg->dump(mgr.getLangOptions());
}
}
-static void ActionCFGView(AnalysisManager& mgr, Decl *D) {
- if (CFG* c = mgr.getCFG(D)) {
- mgr.DisplayFunction(D);
- c->viewCFG(mgr.getLangOptions());
+static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
+ if (CFG *cfg = mgr.getCFG(D)) {
+ C.DisplayFunction(D);
+ cfg->viewCFG(mgr.getLangOptions());
}
}
-static void ActionSecuritySyntacticChecks(AnalysisManager &mgr, Decl *D) {
+static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
+ AnalysisManager &mgr, Decl *D) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
CheckSecuritySyntaxOnly(D, BR);
}
-static void ActionWarnObjCDealloc(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
return;
+ C.DisplayFunction(D);
BugReporter BR(mgr);
- CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
+ CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
}
-static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
- CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
+ CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
}
-static void ActionWarnObjCMethSigs(AnalysisManager& mgr, Decl *D) {
+static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
+ Decl *D) {
+ C.DisplayFunction(D);
BugReporter BR(mgr);
-
CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
}
-static void ActionInlineCall(AnalysisManager &mgr, Decl *D) {
+static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
+ Decl *D) {
+ C.DisplayFunction(D);
+ BugReporter BR(mgr);
+ CheckSizeofPointer(D, BR);
+}
+
+static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
+ Decl *D) {
if (!D)
return;
+ C.DisplayFunction(D);
llvm::OwningPtr<GRTransferFuncs> TF(CreateCallInliner(mgr.getASTContext()));
// Construct the analysis engine.
diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp
index 13aecf171718..bc56029e73d2 100644
--- a/lib/Frontend/Backend.cpp
+++ b/lib/Frontend/Backend.cpp
@@ -8,12 +8,13 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/ASTConsumers.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Frontend/CompileOptions.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/CodeGen/CodeGenOptions.h"
+#include "clang/CodeGen/ModuleBuilder.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
@@ -40,7 +41,8 @@ using namespace llvm;
namespace {
class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
BackendAction Action;
- CompileOptions CompileOpts;
+ CodeGenOptions CodeGenOpts;
+ TargetOptions TargetOpts;
llvm::raw_ostream *AsmOutStream;
llvm::formatted_raw_ostream FormattedOutStream;
ASTContext *Context;
@@ -75,11 +77,12 @@ namespace {
public:
BackendConsumer(BackendAction action, Diagnostic &Diags,
- const LangOptions &langopts, const CompileOptions &compopts,
- const std::string &infile, llvm::raw_ostream* OS,
- LLVMContext& C) :
+ const LangOptions &langopts, const CodeGenOptions &compopts,
+ const TargetOptions &targetopts, const std::string &infile,
+ llvm::raw_ostream* OS, LLVMContext& C) :
Action(action),
- CompileOpts(compopts),
+ CodeGenOpts(compopts),
+ TargetOpts(targetopts),
AsmOutStream(OS),
LLVMIRGeneration("LLVM IR Generation Time"),
CodeGenerationTime("Code Generation Time"),
@@ -92,7 +95,7 @@ namespace {
formatted_raw_ostream::PRESERVE_STREAM);
// Enable -time-passes if -ftime-report is enabled.
- llvm::TimePassesIsEnabled = CompileOpts.TimePasses;
+ llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
}
~BackendConsumer() {
@@ -106,7 +109,7 @@ namespace {
virtual void Initialize(ASTContext &Ctx) {
Context = &Ctx;
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.startTimer();
Gen->Initialize(Ctx);
@@ -115,7 +118,7 @@ namespace {
ModuleProvider = new ExistingModuleProvider(TheModule);
TheTargetData = new llvm::TargetData(Ctx.Target.getTargetDescription());
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.stopTimer();
}
@@ -124,24 +127,24 @@ namespace {
Context->getSourceManager(),
"LLVM IR generation of declaration");
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.startTimer();
Gen->HandleTopLevelDecl(D);
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.stopTimer();
}
virtual void HandleTranslationUnit(ASTContext &C) {
{
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.startTimer();
Gen->HandleTranslationUnit(C);
- if (CompileOpts.TimePasses)
+ if (CodeGenOpts.TimePasses)
LLVMIRGeneration.stopTimer();
}
@@ -202,7 +205,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
} else if (Action == Backend_EmitLL) {
getPerModulePasses()->add(createPrintModulePass(&FormattedOutStream));
} else {
- bool Fast = CompileOpts.OptimizationLevel == 0;
+ bool Fast = CodeGenOpts.OptimizationLevel == 0;
// Create the TargetMachine for generating code.
std::string Triple = TheModule->getTargetTriple();
@@ -213,12 +216,12 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
}
std::string FeaturesStr;
- if (CompileOpts.CPU.size() || CompileOpts.Features.size()) {
+ if (TargetOpts.CPU.size() || TargetOpts.Features.size()) {
SubtargetFeatures Features;
- Features.setCPU(CompileOpts.CPU);
+ Features.setCPU(TargetOpts.CPU);
for (std::vector<std::string>::iterator
- it = CompileOpts.Features.begin(),
- ie = CompileOpts.Features.end(); it != ie; ++it)
+ it = TargetOpts.Features.begin(),
+ ie = TargetOpts.Features.end(); it != ie; ++it)
Features.AddFeature(*it);
FeaturesStr = Features.getString();
}
@@ -237,7 +240,7 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
FunctionPassManager *PM = getCodeGenPasses();
CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
- switch (CompileOpts.OptimizationLevel) {
+ switch (CodeGenOpts.OptimizationLevel) {
default: break;
case 0: OptLevel = CodeGenOpt::None; break;
case 3: OptLevel = CodeGenOpt::Aggressive; break;
@@ -266,37 +269,44 @@ bool BackendConsumer::AddEmitPasses(std::string &Error) {
}
void BackendConsumer::CreatePasses() {
+ unsigned OptLevel = CodeGenOpts.OptimizationLevel;
+ CodeGenOptions::InliningMethod Inlining = CodeGenOpts.Inlining;
+
+ // Handle disabling of LLVM optimization, where we want to preserve the
+ // internal module before any optimization.
+ if (CodeGenOpts.DisableLLVMOpts) {
+ OptLevel = 0;
+ Inlining = CodeGenOpts.NoInlining;
+ }
+
// In -O0 if checking is disabled, we don't even have per-function passes.
- if (CompileOpts.VerifyModule)
+ if (CodeGenOpts.VerifyModule)
getPerFunctionPasses()->add(createVerifierPass());
// Assume that standard function passes aren't run for -O0.
- if (CompileOpts.OptimizationLevel > 0)
- llvm::createStandardFunctionPasses(getPerFunctionPasses(),
- CompileOpts.OptimizationLevel);
+ if (OptLevel > 0)
+ llvm::createStandardFunctionPasses(getPerFunctionPasses(), OptLevel);
llvm::Pass *InliningPass = 0;
- switch (CompileOpts.Inlining) {
- case CompileOptions::NoInlining: break;
- case CompileOptions::NormalInlining: {
+ switch (Inlining) {
+ case CodeGenOptions::NoInlining: break;
+ case CodeGenOptions::NormalInlining: {
// Inline small functions
- unsigned Threshold = (CompileOpts.OptimizeSize ||
- CompileOpts.OptimizationLevel < 3) ? 50 : 200;
+ unsigned Threshold = (CodeGenOpts.OptimizeSize || OptLevel < 3) ? 50 : 200;
InliningPass = createFunctionInliningPass(Threshold);
break;
}
- case CompileOptions::OnlyAlwaysInlining:
+ case CodeGenOptions::OnlyAlwaysInlining:
InliningPass = createAlwaysInlinerPass(); // Respect always_inline
break;
}
// For now we always create per module passes.
PassManager *PM = getPerModulePasses();
- llvm::createStandardModulePasses(PM, CompileOpts.OptimizationLevel,
- CompileOpts.OptimizeSize,
- CompileOpts.UnitAtATime,
- CompileOpts.UnrollLoops,
- CompileOpts.SimplifyLibCalls,
+ llvm::createStandardModulePasses(PM, OptLevel, CodeGenOpts.OptimizeSize,
+ CodeGenOpts.UnitAtATime,
+ CodeGenOpts.UnrollLoops,
+ CodeGenOpts.SimplifyLibCalls,
/*HaveExceptions=*/true,
InliningPass);
}
@@ -308,7 +318,7 @@ void BackendConsumer::EmitAssembly() {
if (!TheModule || !TheTargetData)
return;
- TimeRegion Region(CompileOpts.TimePasses ? &CodeGenerationTime : 0);
+ TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : 0);
// Make sure IR generation is happy with the module. This is
// released by the module provider.
@@ -363,10 +373,11 @@ void BackendConsumer::EmitAssembly() {
ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &LangOpts,
- const CompileOptions &CompileOpts,
+ const CodeGenOptions &CodeGenOpts,
+ const TargetOptions &TargetOpts,
const std::string& InFile,
llvm::raw_ostream* OS,
LLVMContext& C) {
- return new BackendConsumer(Action, Diags, LangOpts, CompileOpts,
- InFile, OS, C);
+ return new BackendConsumer(Action, Diags, LangOpts, CodeGenOpts,
+ TargetOpts, InFile, OS, C);
}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index e3ec78627da0..3f0f43099c69 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -6,17 +6,21 @@ add_clang_library(clangFrontend
AnalysisConsumer.cpp
Backend.cpp
CacheTokens.cpp
+ CompilerInstance.cpp
+ CompilerInvocation.cpp
DeclXML.cpp
DependencyFile.cpp
DiagChecker.cpp
DocumentXML.cpp
FixItRewriter.cpp
+ FrontendAction.cpp
+ FrontendActions.cpp
+ FrontendOptions.cpp
GeneratePCH.cpp
HTMLDiagnostics.cpp
HTMLPrint.cpp
InitHeaderSearch.cpp
InitPreprocessor.cpp
- ManagerRegistry.cpp
PCHReader.cpp
PCHReaderDecl.cpp
PCHReaderStmt.cpp
@@ -34,6 +38,7 @@ add_clang_library(clangFrontend
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
TypeXML.cpp
+ VerifyDiagnosticsClient.cpp
Warnings.cpp
)
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
new file mode 100644
index 000000000000..0365761c840e
--- /dev/null
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -0,0 +1,403 @@
+//===--- CompilerInstance.cpp ---------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PTHManager.h"
+#include "clang/Frontend/ChainedDiagnosticClient.h"
+#include "clang/Frontend/PCHReader.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Path.h"
+using namespace clang;
+
+CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext,
+ bool _OwnsLLVMContext)
+ : LLVMContext(_LLVMContext),
+ OwnsLLVMContext(_OwnsLLVMContext) {
+ }
+
+CompilerInstance::~CompilerInstance() {
+ if (OwnsLLVMContext)
+ delete LLVMContext;
+}
+
+void CompilerInstance::setDiagnostics(Diagnostic *Value) {
+ Diagnostics.reset(Value);
+}
+
+void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
+ DiagClient.reset(Value);
+}
+
+void CompilerInstance::setTarget(TargetInfo *Value) {
+ Target.reset(Value);
+}
+
+void CompilerInstance::setFileManager(FileManager *Value) {
+ FileMgr.reset(Value);
+}
+
+void CompilerInstance::setSourceManager(SourceManager *Value) {
+ SourceMgr.reset(Value);
+}
+
+void CompilerInstance::setPreprocessor(Preprocessor *Value) {
+ PP.reset(Value);
+}
+
+void CompilerInstance::setASTContext(ASTContext *Value) {
+ Context.reset(Value);
+}
+
+void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
+ Consumer.reset(Value);
+}
+
+void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
+ CompletionConsumer.reset(Value);
+}
+
+// Diagnostics
+
+static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
+ unsigned argc, char **argv,
+ llvm::OwningPtr<DiagnosticClient> &DiagClient) {
+ std::string ErrorInfo;
+ llvm::raw_ostream *OS =
+ new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo);
+ if (!ErrorInfo.empty()) {
+ // FIXME: Do not fail like this.
+ llvm::errs() << "error opening -dump-build-information file '"
+ << DiagOpts.DumpBuildInformation << "', option ignored!\n";
+ delete OS;
+ return;
+ }
+
+ (*OS) << "clang-cc command line arguments: ";
+ for (unsigned i = 0; i != argc; ++i)
+ (*OS) << argv[i] << ' ';
+ (*OS) << '\n';
+
+ // Chain in a diagnostic client which will log the diagnostics.
+ DiagnosticClient *Logger =
+ new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true);
+ DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger));
+}
+
+void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
+ Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
+
+ if (Diagnostics)
+ DiagClient.reset(Diagnostics->getClient());
+}
+
+Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
+ int Argc, char **Argv) {
+ llvm::OwningPtr<Diagnostic> Diags(new Diagnostic());
+
+ // Create the diagnostic client for reporting errors or for
+ // implementing -verify.
+ llvm::OwningPtr<DiagnosticClient> DiagClient(
+ new TextDiagnosticPrinter(llvm::errs(), Opts));
+
+ // Chain in -verify checker, if requested.
+ if (Opts.VerifyDiagnostics)
+ DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
+
+ if (!Opts.DumpBuildInformation.empty())
+ SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient);
+
+ // Configure our handling of diagnostics.
+ Diags->setClient(DiagClient.take());
+ if (ProcessWarningOptions(*Diags, Opts))
+ return 0;
+
+ return Diags.take();
+}
+
+// File Manager
+
+void CompilerInstance::createFileManager() {
+ FileMgr.reset(new FileManager());
+}
+
+// Source Manager
+
+void CompilerInstance::createSourceManager() {
+ SourceMgr.reset(new SourceManager());
+}
+
+// Preprocessor
+
+void CompilerInstance::createPreprocessor() {
+ PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
+ getPreprocessorOpts(), getHeaderSearchOpts(),
+ getDependencyOutputOpts(), getTarget(),
+ getSourceManager(), getFileManager()));
+}
+
+Preprocessor *
+CompilerInstance::createPreprocessor(Diagnostic &Diags,
+ const LangOptions &LangInfo,
+ const PreprocessorOptions &PPOpts,
+ const HeaderSearchOptions &HSOpts,
+ const DependencyOutputOptions &DepOpts,
+ const TargetInfo &Target,
+ SourceManager &SourceMgr,
+ FileManager &FileMgr) {
+ // Create a PTH manager if we are using some form of a token cache.
+ PTHManager *PTHMgr = 0;
+ 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,
+ SourceMgr, *HeaderInfo, PTHMgr,
+ /*OwnsHeaderSearch=*/true);
+
+ // Note that this is different then passing PTHMgr to Preprocessor's ctor.
+ // That argument is used as the IdentifierInfoLookup argument to
+ // IdentifierTable's ctor.
+ if (PTHMgr) {
+ PTHMgr->setPreprocessor(PP);
+ PP->setPTHManager(PTHMgr);
+ }
+
+ InitializePreprocessor(*PP, PPOpts, HSOpts);
+
+ // Handle generating dependencies, if requested.
+ if (!DepOpts.OutputFile.empty())
+ AttachDependencyFileGen(*PP, DepOpts);
+
+ return PP;
+}
+
+// ASTContext
+
+void CompilerInstance::createASTContext() {
+ Preprocessor &PP = getPreprocessor();
+ Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
+ getTarget(), PP.getIdentifierTable(),
+ PP.getSelectorTable(), PP.getBuiltinInfo(),
+ /*FreeMemory=*/ !getFrontendOpts().DisableFree,
+ /*size_reserve=*/ 0));
+}
+
+// ExternalASTSource
+
+void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
+ llvm::OwningPtr<ExternalASTSource> Source;
+ Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
+ getPreprocessor(), getASTContext()));
+ getASTContext().setExternalSource(Source);
+}
+
+ExternalASTSource *
+CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
+ const std::string &Sysroot,
+ Preprocessor &PP,
+ ASTContext &Context) {
+ llvm::OwningPtr<PCHReader> Reader;
+ Reader.reset(new PCHReader(PP, &Context,
+ Sysroot.empty() ? 0 : Sysroot.c_str()));
+
+ switch (Reader->ReadPCH(Path)) {
+ case PCHReader::Success:
+ // Set the predefines buffer as suggested by the PCH reader. Typically, the
+ // predefines buffer will be empty.
+ PP.setPredefines(Reader->getSuggestedPredefines());
+ return Reader.take();
+
+ case PCHReader::Failure:
+ // Unrecoverable failure: don't even try to process the input file.
+ break;
+
+ case PCHReader::IgnorePCH:
+ // No suitable PCH file could be found. Return an error.
+ break;
+ }
+
+ return 0;
+}
+
+// Code Completion
+
+void CompilerInstance::createCodeCompletionConsumer() {
+ const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
+ CompletionConsumer.reset(
+ createCodeCompletionConsumer(getPreprocessor(),
+ Loc.FileName, Loc.Line, Loc.Column,
+ getFrontendOpts().DebugCodeCompletionPrinter,
+ getFrontendOpts().ShowMacrosInCodeCompletion,
+ llvm::outs()));
+}
+
+CodeCompleteConsumer *
+CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
+ const std::string &Filename,
+ unsigned Line,
+ unsigned Column,
+ bool UseDebugPrinter,
+ bool ShowMacros,
+ llvm::raw_ostream &OS) {
+ // Tell the source manager to chop off the given file at a specific
+ // line and column.
+ const FileEntry *Entry = PP.getFileManager().getFile(Filename);
+ if (!Entry) {
+ PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
+ << Filename;
+ return 0;
+ }
+
+ // Truncate the named file at the given line/column.
+ PP.getSourceManager().truncateFileAt(Entry, Line, Column);
+
+ // Set up the creation routine for code-completion.
+ if (UseDebugPrinter)
+ return new PrintingCodeCompleteConsumer(ShowMacros, OS);
+ else
+ return new CIndexCodeCompleteConsumer(ShowMacros, OS);
+}
+
+// Output Files
+
+void CompilerInstance::addOutputFile(llvm::StringRef Path,
+ llvm::raw_ostream *OS) {
+ assert(OS && "Attempt to add empty stream to output list!");
+ OutputFiles.push_back(std::make_pair(Path, OS));
+}
+
+void CompilerInstance::ClearOutputFiles(bool EraseFiles) {
+ for (std::list< std::pair<std::string, llvm::raw_ostream*> >::iterator
+ it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
+ delete it->second;
+ if (EraseFiles && !it->first.empty())
+ llvm::sys::Path(it->first).eraseFromDisk();
+ }
+ OutputFiles.clear();
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createDefaultOutputFile(bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ return createOutputFile(getFrontendOpts().OutputFile, Binary,
+ InFile, Extension);
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension) {
+ std::string Error, OutputPathName;
+ llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
+ InFile, Extension,
+ &OutputPathName);
+ if (!OS) {
+ // FIXME: Don't fail this way.
+ llvm::errs() << "ERROR: " << Error << "\n";
+ ::exit(1);
+ }
+
+ // Add the output file -- but don't try to remove "-", since this means we are
+ // using stdin.
+ addOutputFile((OutputPathName != "-") ? OutputPathName : "", OS);
+
+ return OS;
+}
+
+llvm::raw_fd_ostream *
+CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
+ std::string &Error,
+ bool Binary,
+ llvm::StringRef InFile,
+ llvm::StringRef Extension,
+ std::string *ResultPathName) {
+ std::string OutFile;
+ if (!OutputPath.empty()) {
+ OutFile = OutputPath;
+ } else if (InFile == "-") {
+ OutFile = "-";
+ } else if (!Extension.empty()) {
+ llvm::sys::Path Path(InFile);
+ Path.eraseSuffix();
+ Path.appendSuffix(Extension);
+ OutFile = Path.str();
+ } else {
+ OutFile = "-";
+ }
+
+ llvm::raw_fd_ostream *OS =
+ new llvm::raw_fd_ostream(OutFile.c_str(), Error,
+ (Binary ? llvm::raw_fd_ostream::F_Binary : 0));
+ if (!OS)
+ return 0;
+
+ if (ResultPathName)
+ *ResultPathName = OutFile;
+
+ return OS;
+}
+
+// Initialization Utilities
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
+ return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
+ getSourceManager(), getFrontendOpts());
+}
+
+bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
+ Diagnostic &Diags,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ const FrontendOptions &Opts) {
+ // Figure out where to get and map in the main file.
+ if (Opts.EmptyInputOnly) {
+ const char *EmptyStr = "";
+ llvm::MemoryBuffer *SB =
+ llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<empty input>");
+ SourceMgr.createMainFileIDForMemBuffer(SB);
+ } else if (InputFile != "-") {
+ const FileEntry *File = FileMgr.getFile(InputFile);
+ if (File) SourceMgr.createMainFileID(File, SourceLocation());
+ if (SourceMgr.getMainFileID().isInvalid()) {
+ Diags.Report(diag::err_fe_error_reading) << InputFile;
+ return false;
+ }
+ } else {
+ llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
+ SourceMgr.createMainFileIDForMemBuffer(SB);
+ if (SourceMgr.getMainFileID().isInvalid()) {
+ Diags.Report(diag::err_fe_error_reading_stdin);
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
new file mode 100644
index 000000000000..ed6d0b71a51b
--- /dev/null
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -0,0 +1,548 @@
+//===--- CompilerInvocation.cpp -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CompilerInvocation.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace clang;
+
+void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
+ const llvm::SmallVectorImpl<llvm::StringRef> &Args) {
+ llvm::llvm_report_error("FIXME: Not yet implemented!");
+}
+
+static const char *getAnalysisName(Analyses Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis store!");
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
+ case NAME: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisStoreName(AnalysisStores Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis store!");
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis constraints!");
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
+ switch (Kind) {
+ default:
+ llvm::llvm_unreachable("Unknown analysis client!");
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
+ case PD_##NAME: return CMDFLAG;
+#include "clang/Frontend/Analyses.def"
+ }
+}
+
+static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
+ std::vector<std::string> &Res) {
+ for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i)
+ Res.push_back(getAnalysisName(Opts.AnalysisList[i]));
+ if (Opts.AnalysisStoreOpt != BasicStoreModel) {
+ Res.push_back("-analyzer-store");
+ Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt));
+ }
+ if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
+ Res.push_back("-analyzer-constraints");
+ Res.push_back(getAnalysisConstraintName(Opts.AnalysisConstraintsOpt));
+ }
+ if (Opts.AnalysisDiagOpt != PD_HTML) {
+ Res.push_back("-analyzer-output");
+ Res.push_back(getAnalysisDiagClientName(Opts.AnalysisDiagOpt));
+ }
+ if (!Opts.AnalyzeSpecificFunction.empty()) {
+ Res.push_back("-analyze-function");
+ Res.push_back(Opts.AnalyzeSpecificFunction);
+ }
+ if (Opts.AnalyzeAll)
+ Res.push_back("-analyzer-opt-analyze-headers");
+ if (Opts.AnalyzerDisplayProgress)
+ Res.push_back("-analyzer-display-progress");
+ if (Opts.EagerlyAssume)
+ Res.push_back("-analyzer-eagerly-assume");
+ if (Opts.PurgeDead)
+ Res.push_back("-analyzer-purge-dead");
+ if (Opts.TrimGraph)
+ Res.push_back("-trim-egraph");
+ if (Opts.VisualizeEGDot)
+ Res.push_back("-analyzer-viz-egraph-graphviz");
+ if (Opts.VisualizeEGDot)
+ Res.push_back("-analyzer-viz-egraph-ubigraph");
+ if (Opts.EnableExperimentalChecks)
+ Res.push_back("-analyzer-experimental-checks");
+ if (Opts.EnableExperimentalInternalChecks)
+ Res.push_back("-analyzer-experimental-internal-checls");
+}
+
+static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.DebugInfo)
+ Res.push_back("-g");
+ if (Opts.DisableLLVMOpts)
+ Res.push_back("-disable-llvm-optzns");
+ if (Opts.DisableRedZone)
+ Res.push_back("-disable-red-zone");
+ if (!Opts.MergeAllConstants)
+ Res.push_back("-fno-merge-all-constants");
+ // NoCommon is only derived.
+ if (Opts.NoImplicitFloat)
+ Res.push_back("-no-implicit-float");
+ if (Opts.OptimizeSize) {
+ assert(Opts.OptimizationLevel == 2 && "Invalid options!");
+ Res.push_back("-Os");
+ } else if (Opts.OptimizationLevel == 0)
+ Res.push_back("-O" + Opts.OptimizationLevel);
+ // SimplifyLibCalls is only derived.
+ // TimePasses is only derived.
+ // UnitAtATime is unused.
+ // UnrollLoops is only derived.
+ // VerifyModule is only derived.
+ // Inlining is only derived.
+}
+
+static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.IncludeSystemHeaders)
+ Res.push_back("-sys-header-deps");
+ if (Opts.UsePhonyTargets)
+ Res.push_back("-MP");
+ if (!Opts.OutputFile.empty()) {
+ Res.push_back("-dependency-file");
+ Res.push_back(Opts.OutputFile);
+ }
+ for (unsigned i = 0, e = Opts.Targets.size(); i != e; ++i) {
+ Res.push_back("-MT");
+ Res.push_back(Opts.Targets[i]);
+ }
+}
+
+static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.IgnoreWarnings)
+ Res.push_back("-w");
+ if (Opts.NoRewriteMacros)
+ Res.push_back("-Wno-rewrite-macros");
+ if (Opts.Pedantic)
+ Res.push_back("-pedantic");
+ if (Opts.PedanticErrors)
+ Res.push_back("-pedantic-errors");
+ if (!Opts.ShowColumn)
+ Res.push_back("-fno-show-column");
+ if (!Opts.ShowLocation)
+ Res.push_back("-fno-show-source-location");
+ if (!Opts.ShowCarets)
+ Res.push_back("-fno-caret-diagnostics");
+ if (!Opts.ShowFixits)
+ Res.push_back("-fno-diagnostics-fixit-info");
+ if (Opts.ShowSourceRanges)
+ Res.push_back("-fdiagnostics-print-source-range-info");
+ if (Opts.ShowColors)
+ Res.push_back("-fcolor-diagnostics");
+ if (Opts.VerifyDiagnostics)
+ Res.push_back("-verify");
+ if (Opts.ShowOptionNames)
+ Res.push_back("-fdiagnostics-show-option");
+ if (Opts.MessageLength) {
+ Res.push_back("-fmessage-length");
+ Res.push_back(llvm::utostr(Opts.MessageLength));
+ }
+ if (!Opts.DumpBuildInformation.empty()) {
+ Res.push_back("-dump-build-information");
+ Res.push_back(Opts.DumpBuildInformation);
+ }
+ for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i)
+ Res.push_back("-W" + Opts.Warnings[i]);
+}
+
+static const char *getInputKindName(FrontendOptions::InputKind Kind) {
+ switch (Kind) {
+ case FrontendOptions::IK_None: break;
+ case FrontendOptions::IK_AST: return "ast";
+ case FrontendOptions::IK_Asm: return "assembler-with-cpp";
+ case FrontendOptions::IK_C: return "c";
+ case FrontendOptions::IK_CXX: return "c++";
+ case FrontendOptions::IK_ObjC: return "objective-c";
+ case FrontendOptions::IK_ObjCXX: return "objective-c++";
+ case FrontendOptions::IK_OpenCL: return "cl";
+ case FrontendOptions::IK_PreprocessedC: return "cpp-output";
+ case FrontendOptions::IK_PreprocessedCXX: return "c++-cpp-output";
+ case FrontendOptions::IK_PreprocessedObjC: return "objective-c-cpp-output";
+ case FrontendOptions::IK_PreprocessedObjCXX: return "objective-c++-cpp-output";
+ }
+
+ llvm::llvm_unreachable("Unexpected language kind!");
+ return 0;
+}
+
+static const char *getActionName(frontend::ActionKind Kind) {
+ switch (Kind) {
+ case frontend::PluginAction:
+ case frontend::InheritanceView:
+ llvm::llvm_unreachable("Invalid kind!");
+
+ case frontend::ASTDump: return "-ast-dump";
+ case frontend::ASTPrint: return "-ast-print";
+ case frontend::ASTPrintXML: return "-ast-print-xml";
+ case frontend::ASTView: return "-ast-view";
+ case frontend::DumpRawTokens: return "-dump-raw-tokens";
+ case frontend::DumpRecordLayouts: return "-dump-record-layouts";
+ case frontend::DumpTokens: return "-dump-tokens";
+ case frontend::EmitAssembly: return "-S";
+ case frontend::EmitBC: return "-emit-llvm-bc";
+ case frontend::EmitHTML: return "-emit-html";
+ case frontend::EmitLLVM: return "-emit-llvm";
+ case frontend::EmitLLVMOnly: return "-emit-llvm-only";
+ case frontend::FixIt: return "-fixit";
+ case frontend::GeneratePCH: return "-emit-pch";
+ case frontend::GeneratePTH: return "-emit-pth";
+ case frontend::ParseNoop: return "-parse-noop";
+ case frontend::ParsePrintCallbacks: return "-parse-print-callbacks";
+ case frontend::ParseSyntaxOnly: return "-fsyntax-only";
+ case frontend::PrintDeclContext: return "-print-decl-contexts";
+ case frontend::PrintPreprocessedInput: return "-E";
+ case frontend::RewriteBlocks: return "-rewrite-blocks";
+ case frontend::RewriteMacros: return "-rewrite-macros";
+ case frontend::RewriteObjC: return "-rewrite-objc";
+ case frontend::RewriteTest: return "-rewrite-test";
+ case frontend::RunAnalysis: return "-analyze";
+ case frontend::RunPreprocessorOnly: return "-Eonly";
+ }
+
+ llvm::llvm_unreachable("Unexpected language kind!");
+ return 0;
+}
+
+static void FrontendOptsToArgs(const FrontendOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (!Opts.DebugCodeCompletionPrinter)
+ Res.push_back("-code-completion-debug-printer=0");
+ if (Opts.DisableFree)
+ Res.push_back("-disable-free");
+ if (Opts.EmptyInputOnly)
+ Res.push_back("-empty-input-only");
+ if (Opts.RelocatablePCH)
+ Res.push_back("-relocatable-pch");
+ if (Opts.ShowMacrosInCodeCompletion)
+ Res.push_back("-code-completion-macros");
+ if (Opts.ShowStats)
+ Res.push_back("-stats");
+ if (Opts.ShowTimers)
+ Res.push_back("-ftime-report");
+
+ bool NeedLang = false;
+ for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
+ if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].second) !=
+ Opts.Inputs[i].first)
+ NeedLang = true;
+ if (NeedLang) {
+ Res.push_back("-x");
+ Res.push_back(getInputKindName(Opts.Inputs[0].first));
+ }
+ for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
+ assert((!NeedLang || Opts.Inputs[i].first == Opts.Inputs[0].first) &&
+ "Unable to represent this input vector!");
+ Res.push_back(Opts.Inputs[i].second);
+ }
+
+ if (!Opts.OutputFile.empty()) {
+ Res.push_back("-o");
+ Res.push_back(Opts.OutputFile);
+ }
+ if (!Opts.ViewClassInheritance.empty()) {
+ Res.push_back("-cxx-inheritance-view");
+ Res.push_back(Opts.ViewClassInheritance);
+ }
+ for (unsigned i = 0, e = Opts.FixItLocations.size(); i != e; ++i) {
+ Res.push_back("-fixit-at");
+ Res.push_back(Opts.FixItLocations[i].FileName + ":" +
+ llvm::utostr(Opts.FixItLocations[i].Line) + ":" +
+ llvm::utostr(Opts.FixItLocations[i].Column));
+ }
+ if (!Opts.CodeCompletionAt.FileName.empty()) {
+ Res.push_back("-code-completion-at");
+ Res.push_back(Opts.CodeCompletionAt.FileName + ":" +
+ llvm::utostr(Opts.CodeCompletionAt.Line) + ":" +
+ llvm::utostr(Opts.CodeCompletionAt.Column));
+ }
+ if (Opts.ProgramAction != frontend::InheritanceView &&
+ Opts.ProgramAction != frontend::PluginAction)
+ Res.push_back(getActionName(Opts.ProgramAction));
+ if (!Opts.ActionName.empty()) {
+ Res.push_back("-plugin");
+ Res.push_back(Opts.ActionName);
+ }
+}
+
+static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (Opts.Sysroot.empty()) {
+ Res.push_back("-isysroot");
+ Res.push_back(Opts.Sysroot);
+ }
+
+ /// User specified include entries.
+ for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
+ const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
+ if (E.IsFramework && (E.Group != frontend::Angled || E.IsUserSupplied))
+ llvm::llvm_report_error("Invalid option set!");
+ if (E.IsUserSupplied) {
+ if (E.Group == frontend::After) {
+ Res.push_back("-idirafter");
+ } else if (E.Group == frontend::Quoted) {
+ Res.push_back("-iquoted");
+ } else if (E.Group == frontend::System) {
+ Res.push_back("-isystem");
+ } else {
+ assert(E.Group == frontend::Angled && "Invalid group!");
+ Res.push_back(E.IsFramework ? "-F" : "-I");
+ }
+ } else {
+ if (E.Group != frontend::Angled && E.Group != frontend::System)
+ llvm::llvm_report_error("Invalid option set!");
+ Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" :
+ "-iwithprefix");
+ }
+ Res.push_back(E.Path);
+ }
+
+ if (!Opts.EnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.CEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.ObjCEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.CXXEnvIncPath.empty()) {
+ // FIXME: Provide an option for this, and move env detection to driver.
+ llvm::llvm_report_error("Not yet implemented!");
+ }
+ if (!Opts.ObjCXXEnvIncPath.empty()) {
+ // 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.UseStandardIncludes)
+ Res.push_back("-nostdinc");
+ if (Opts.Verbose)
+ Res.push_back("-v");
+}
+
+static void LangOptsToArgs(const LangOptions &Opts,
+ std::vector<std::string> &Res) {
+ LangOptions DefaultLangOpts;
+
+ // FIXME: Need to set -std to get all the implicit options.
+
+ // FIXME: We want to only pass options relative to the defaults, which
+ // requires constructing a target. :(
+ //
+ // It would be better to push the all target specific choices into the driver,
+ // so that everything below that was more uniform.
+
+ if (Opts.Trigraphs)
+ Res.push_back("-trigraphs");
+ // Implicit based on the input kind:
+ // AsmPreprocessor, CPlusPlus, ObjC1, ObjC2, OpenCL
+ // Implicit based on the input language standard:
+ // BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
+ if (Opts.DollarIdents)
+ Res.push_back("-fdollars-in-identifiers");
+ if (Opts.Microsoft)
+ Res.push_back("-fms-extensions=1");
+ if (Opts.ObjCNonFragileABI)
+ Res.push_back("-fobjc-nonfragile-abi");
+ // NoInline is implicit.
+ if (!Opts.CXXOperatorNames)
+ Res.push_back("-fno-operator-names");
+ if (Opts.PascalStrings)
+ Res.push_back("-fpascal-strings");
+ if (Opts.WritableStrings)
+ Res.push_back("-fwritable-strings");
+ if (!Opts.LaxVectorConversions)
+ Res.push_back("-fno-lax-vector-conversions");
+ if (Opts.AltiVec)
+ Res.push_back("-faltivec");
+ Res.push_back("-fexceptions");
+ Res.push_back(Opts.Exceptions ? "1" : "0");
+ Res.push_back("-frtti");
+ Res.push_back(Opts.Rtti ? "1" : "0");
+ if (!Opts.NeXTRuntime)
+ Res.push_back("-fgnu-runtime");
+ if (Opts.Freestanding)
+ Res.push_back("-ffreestanding");
+ if (Opts.NoBuiltin)
+ Res.push_back("-fno-builtin");
+ if (Opts.ThreadsafeStatics)
+ llvm::llvm_report_error("FIXME: Not yet implemented!");
+ if (Opts.POSIXThreads)
+ Res.push_back("-pthread");
+ if (Opts.Blocks)
+ Res.push_back("-fblocks=1");
+ if (Opts.EmitAllDecls)
+ Res.push_back("-femit-all-decls");
+ if (!Opts.MathErrno)
+ Res.push_back("-fmath-errno=0");
+ if (Opts.OverflowChecking)
+ Res.push_back("-ftrapv");
+ if (Opts.HeinousExtensions)
+ Res.push_back("-fheinous-gnu-extensions");
+ // Optimize is implicit.
+ // OptimizeSize is implicit.
+ if (Opts.Static)
+ Res.push_back("-static-define");
+ if (Opts.PICLevel) {
+ Res.push_back("-pic-level");
+ Res.push_back(llvm::utostr(Opts.PICLevel));
+ }
+ if (Opts.ObjCGCBitmapPrint)
+ Res.push_back("-print-ivar-layout");
+ Res.push_back("-faccess-control");
+ Res.push_back(Opts.AccessControl ? "1" : "0");
+ Res.push_back("-fsigned-char");
+ Res.push_back(Opts.CharIsSigned ? "1" : "0");
+ Res.push_back("-fshort-wchar");
+ Res.push_back(Opts.ShortWChar ? "1" : "0");
+ if (!Opts.ElideConstructors)
+ Res.push_back("-fno-elide-constructors");
+ if (Opts.getGCMode() != LangOptions::NonGC) {
+ if (Opts.getGCMode() == LangOptions::HybridGC) {
+ Res.push_back("-fobjc-gc");
+ } else {
+ assert(Opts.getGCMode() == LangOptions::GCOnly && "Invalid GC mode!");
+ Res.push_back("-fobjc-gc-only");
+ }
+ }
+ if (Opts.getVisibilityMode() != LangOptions::Default) {
+ Res.push_back("-fvisibility");
+ if (Opts.getVisibilityMode() == LangOptions::Hidden) {
+ Res.push_back("default");
+ } else {
+ assert(Opts.getVisibilityMode() == LangOptions::Protected &&
+ "Invalid visibility!");
+ Res.push_back("protected");
+ }
+ }
+ if (Opts.getStackProtectorMode() != 0) {
+ Res.push_back("-stack-protector");
+ Res.push_back(llvm::utostr(Opts.getStackProtectorMode()));
+ }
+ if (Opts.getMainFileName()) {
+ Res.push_back("-main-file-name");
+ Res.push_back(Opts.getMainFileName());
+ }
+ if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth) {
+ Res.push_back("-ftemplate-depth");
+ Res.push_back(llvm::utostr(Opts.InstantiationDepth));
+ }
+ if (Opts.ObjCConstantStringClass) {
+ Res.push_back("-fconstant-string-class");
+ Res.push_back(Opts.ObjCConstantStringClass);
+ }
+}
+
+static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
+ std::vector<std::string> &Res) {
+ for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i)
+ Res.push_back((Opts.Macros[i].second ? "-U" : "-D") + Opts.Macros[i].first);
+ for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) {
+ Res.push_back("-include");
+ Res.push_back(Opts.Includes[i]);
+ }
+ for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i) {
+ Res.push_back("-imacros");
+ Res.push_back(Opts.Includes[i]);
+ }
+ if (!Opts.UsePredefines)
+ Res.push_back("-undef");
+ if (!Opts.ImplicitPCHInclude.empty()) {
+ Res.push_back("-implicit-pch-include");
+ Res.push_back(Opts.ImplicitPCHInclude);
+ }
+ if (!Opts.ImplicitPTHInclude.empty()) {
+ Res.push_back("-implicit-pth-include");
+ Res.push_back(Opts.ImplicitPTHInclude);
+ }
+ if (!Opts.TokenCache.empty()) {
+ Res.push_back("-token-cache");
+ Res.push_back(Opts.TokenCache);
+ }
+}
+
+static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (!Opts.ShowCPP && !Opts.ShowMacros)
+ llvm::llvm_report_error("Invalid option combination!");
+
+ if (Opts.ShowCPP && Opts.ShowMacros)
+ Res.push_back("-dD");
+ else if (!Opts.ShowCPP && Opts.ShowMacros)
+ Res.push_back("-dM");
+
+ if (!Opts.ShowLineMarkers)
+ Res.push_back("-P");
+ if (Opts.ShowComments)
+ Res.push_back("-C");
+ if (Opts.ShowMacroComments)
+ Res.push_back("-CC");
+}
+
+static void TargetOptsToArgs(const TargetOptions &Opts,
+ std::vector<std::string> &Res) {
+ Res.push_back("-triple");
+ Res.push_back(Opts.Triple);
+ if (!Opts.CPU.empty()) {
+ Res.push_back("-target-cpu");
+ Res.push_back(Opts.CPU);
+ }
+ if (!Opts.ABI.empty()) {
+ Res.push_back("-target-abi");
+ Res.push_back(Opts.ABI);
+ }
+ for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) {
+ Res.push_back("-target-feature");
+ Res.push_back(Opts.Features[i]);
+ }
+}
+
+void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
+ AnalyzerOptsToArgs(getAnalyzerOpts(), Res);
+ CodeGenOptsToArgs(getCodeGenOpts(), Res);
+ DependencyOutputOptsToArgs(getDependencyOutputOpts(), Res);
+ DiagnosticOptsToArgs(getDiagnosticOpts(), Res);
+ FrontendOptsToArgs(getFrontendOpts(), Res);
+ HeaderSearchOptsToArgs(getHeaderSearchOpts(), Res);
+ LangOptsToArgs(getLangOpts(), Res);
+ PreprocessorOptsToArgs(getPreprocessorOpts(), Res);
+ PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), Res);
+ TargetOptsToArgs(getTargetOpts(), Res);
+}
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index 81d1179f28e3..c7f93595e1ea 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -12,12 +12,14 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/Utils.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/PPCallbacks.h"
-#include "clang/Lex/DirectoryLookup.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
@@ -42,11 +44,10 @@ private:
public:
DependencyFileCallback(const Preprocessor *_PP,
llvm::raw_ostream *_OS,
- const std::vector<std::string> &_Targets,
- bool _IncludeSystemHeaders,
- bool _PhonyTarget)
- : PP(_PP), Targets(_Targets), OS(_OS),
- IncludeSystemHeaders(_IncludeSystemHeaders), PhonyTarget(_PhonyTarget) {}
+ const DependencyOutputOptions &Opts)
+ : PP(_PP), Targets(Opts.Targets), OS(_OS),
+ IncludeSystemHeaders(Opts.IncludeSystemHeaders),
+ PhonyTarget(Opts.UsePhonyTargets) {}
~DependencyFileCallback() {
OutputDependencyFile();
@@ -59,18 +60,23 @@ public:
};
}
+void clang::AttachDependencyFileGen(Preprocessor &PP,
+ const DependencyOutputOptions &Opts) {
+ if (Opts.Targets.empty()) {
+ PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT);
+ return;
+ }
+ std::string Err;
+ llvm::raw_ostream *OS(new llvm::raw_fd_ostream(Opts.OutputFile.c_str(), Err));
+ if (!Err.empty()) {
+ PP.getDiagnostics().Report(diag::err_fe_error_opening)
+ << Opts.OutputFile << Err;
+ return;
+ }
-void clang::AttachDependencyFileGen(Preprocessor *PP, llvm::raw_ostream *OS,
- std::vector<std::string> &Targets,
- bool IncludeSystemHeaders,
- bool PhonyTarget) {
- assert(!Targets.empty() && "Target required for dependency generation");
-
- DependencyFileCallback *PPDep =
- new DependencyFileCallback(PP, OS, Targets, IncludeSystemHeaders,
- PhonyTarget);
- PP->setPPCallbacks(PPDep);
+ assert(!PP.getPPCallbacks() && "Preprocessor callbacks already registered!");
+ PP.setPPCallbacks(new DependencyFileCallback(&PP, OS, Opts));
}
/// FileMatchesDepCriteria - Determine whether the given Filename should be
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index d92d4cb7b8de..0263c30bfd57 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -135,7 +135,7 @@ void DocumentXML::finalize() {
for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end();
i != e; ++i) {
- if (i->first.hasQualifiers()) {
+ if (i->first.hasLocalQualifiers()) {
writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
@@ -205,7 +205,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType)
{
addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
- if (!pType.hasQualifiers())
+ if (!pType.hasLocalQualifiers())
{
Types[pType] = BasicTypes[pType.getTypePtr()];
}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
new file mode 100644
index 000000000000..ff63a0dab5f9
--- /dev/null
+++ b/lib/Frontend/FrontendAction.cpp
@@ -0,0 +1,225 @@
+//===--- FrontendAction.cpp -----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Sema/ParseAST.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+FrontendAction::FrontendAction() : Instance(0), CurrentTimer(0) {}
+
+FrontendAction::~FrontendAction() {}
+
+void FrontendAction::setCurrentFile(llvm::StringRef Value, ASTUnit *AST) {
+ CurrentFile = Value;
+ CurrentASTUnit.reset(AST);
+}
+
+bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
+ llvm::StringRef Filename,
+ bool IsAST) {
+ assert(!Instance && "Already processing a source file!");
+ assert(!Filename.empty() && "Unexpected empty filename!");
+ setCurrentFile(Filename);
+ setCompilerInstance(&CI);
+
+ // AST files follow a very different path, since they share objects via the
+ // AST unit.
+ if (IsAST) {
+ assert(!usesPreprocessorOnly() &&
+ "Attempt to pass AST file to preprocessor only action!");
+ 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;
+ goto failure;
+ }
+
+ setCurrentFile(Filename, AST);
+
+ // Set the shared objects, these are reset when we finish processing the
+ // file, otherwise the CompilerInstance will happily destroy them.
+ CI.setFileManager(&AST->getFileManager());
+ CI.setSourceManager(&AST->getSourceManager());
+ CI.setPreprocessor(&AST->getPreprocessor());
+ CI.setASTContext(&AST->getASTContext());
+
+ // Initialize the action.
+ if (!BeginSourceFileAction(CI, Filename))
+ goto failure;
+
+ /// Create the AST consumer.
+ CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+ if (!CI.hasASTConsumer())
+ goto failure;
+
+ return true;
+ }
+
+ // Inform the diagnostic client we are processing a source file.
+ CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
+ &CI.getPreprocessor());
+
+ // Initialize the action.
+ if (!BeginSourceFileAction(CI, Filename))
+ goto failure;
+
+ /// Create the AST context and consumer unless this is a preprocessor only
+ /// action.
+ if (!usesPreprocessorOnly()) {
+ CI.createASTContext();
+ CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+ if (!CI.hasASTConsumer())
+ goto failure;
+
+ /// Use PCH?
+ if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
+ assert(hasPCHSupport() && "This action does not have PCH support!");
+ CI.createPCHExternalASTSource(
+ CI.getPreprocessorOpts().ImplicitPCHInclude);
+ if (!CI.getASTContext().getExternalSource())
+ goto failure;
+ }
+ }
+
+ // Initialize builtin info as long as we aren't using an external AST
+ // source.
+ if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) {
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
+ PP.getLangOptions().NoBuiltin);
+ }
+
+ return true;
+
+ // If we failed, reset state since the client will not end up calling the
+ // matching EndSourceFile().
+ failure:
+ if (isCurrentFileAST()) {
+ CI.takeASTContext();
+ CI.takePreprocessor();
+ CI.takeSourceManager();
+ CI.takeFileManager();
+ }
+
+ CI.getDiagnosticClient().EndSourceFile();
+ setCurrentFile("");
+ setCompilerInstance(0);
+ return false;
+}
+
+void FrontendAction::Execute() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // Initialize the main file entry. This needs to be delayed until after PCH
+ // has loaded.
+ if (isCurrentFileAST()) {
+ // Set the main file ID to an empty file.
+ //
+ // FIXME: We probably shouldn't need this, but for now this is the
+ // simplest way to reuse the logic in ParseAST.
+ const char *EmptyStr = "";
+ llvm::MemoryBuffer *SB =
+ llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>");
+ CI.getSourceManager().createMainFileIDForMemBuffer(SB);
+ } else {
+ if (!CI.InitializeSourceManager(getCurrentFile()))
+ return;
+ }
+
+ llvm::TimeRegion Timer(CurrentTimer);
+ ExecuteAction();
+}
+
+void FrontendAction::EndSourceFile() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // Finalize the action.
+ EndSourceFileAction();
+
+ // Release the consumer and the AST, in that order since the consumer may
+ // perform actions in its destructor which require the context.
+ //
+ // FIXME: There is more per-file stuff we could just drop here?
+ if (CI.getFrontendOpts().DisableFree) {
+ CI.takeASTConsumer();
+ if (!isCurrentFileAST())
+ CI.takeASTContext();
+ } else {
+ CI.setASTConsumer(0);
+ if (!isCurrentFileAST())
+ CI.setASTContext(0);
+ }
+
+ if (CI.getFrontendOpts().ShowStats) {
+ llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
+ CI.getPreprocessor().PrintStats();
+ CI.getPreprocessor().getIdentifierTable().PrintStats();
+ CI.getPreprocessor().getHeaderSearchInfo().PrintStats();
+ CI.getSourceManager().PrintStats();
+ llvm::errs() << "\n";
+ }
+
+ // Cleanup the output streams, and erase the output files if we encountered
+ // an error.
+ CI.ClearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().getNumErrors());
+
+ // Inform the diagnostic client we are done with this source file.
+ CI.getDiagnosticClient().EndSourceFile();
+
+ if (isCurrentFileAST()) {
+ CI.takeASTContext();
+ CI.takePreprocessor();
+ CI.takeSourceManager();
+ CI.takeFileManager();
+ }
+
+ setCompilerInstance(0);
+ setCurrentFile("");
+}
+
+//===----------------------------------------------------------------------===//
+// Utility Actions
+//===----------------------------------------------------------------------===//
+
+void ASTFrontendAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+
+ // FIXME: Move the truncation aspect of this into Sema, we delayed this till
+ // here so the source manager would be initialized.
+ if (hasCodeCompletionSupport() &&
+ !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
+ CI.createCodeCompletionConsumer();
+
+ // Use a code completion consumer?
+ CodeCompleteConsumer *CompletionConsumer = 0;
+ if (CI.hasCodeCompletionConsumer())
+ CompletionConsumer = &CI.getCodeCompletionConsumer();
+
+ ParseAST(CI.getPreprocessor(), &CI.getASTConsumer(), CI.getASTContext(),
+ CI.getFrontendOpts().ShowStats,
+ usesCompleteTranslationUnit(), CompletionConsumer);
+}
+
+ASTConsumer *
+PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ llvm::llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
+}
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
new file mode 100644
index 000000000000..7a7537bce40f
--- /dev/null
+++ b/lib/Frontend/FrontendActions.cpp
@@ -0,0 +1,281 @@
+//===--- FrontendActions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/AnalysisConsumer.h"
+#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FixItRewriter.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateAnalysisConsumer(CI.getPreprocessor(),
+ CI.getFrontendOpts().OutputFile,
+ CI.getAnalyzerOpts());
+}
+
+ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTPrinter(CI.createDefaultOutputFile(false, InFile));
+}
+
+ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTPrinterXML(CI.createDefaultOutputFile(false, InFile,
+ "xml"));
+}
+
+ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTDumper();
+}
+
+ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateASTViewer();
+}
+
+ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateDeclContextPrinter();
+}
+
+ASTConsumer *DumpRecordAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateRecordLayoutDumper();
+}
+
+ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
+ if (CI.getFrontendOpts().RelocatablePCH &&
+ Sysroot.empty()) {
+ CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
+ return 0;
+ }
+
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
+ if (CI.getFrontendOpts().RelocatablePCH)
+ return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());
+
+ return CreatePCHGenerator(CI.getPreprocessor(), OS);
+}
+
+ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateHTMLPrinter(CI.createDefaultOutputFile(false, InFile),
+ CI.getPreprocessor());
+}
+
+ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
+}
+
+FixItAction::FixItAction() {}
+FixItAction::~FixItAction() {}
+
+ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new ASTConsumer();
+}
+
+/// AddFixItLocations - Add any individual user specified "fix-it" locations,
+/// and return true on success.
+static bool AddFixItLocations(CompilerInstance &CI,
+ FixItRewriter &FixItRewrite) {
+ const std::vector<ParsedSourceLocation> &Locs =
+ CI.getFrontendOpts().FixItLocations;
+ for (unsigned i = 0, e = Locs.size(); i != e; ++i) {
+ const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName);
+ if (!File) {
+ CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file)
+ << Locs[i].FileName;
+ return false;
+ }
+
+ RequestedSourceLocation Requested;
+ Requested.File = File;
+ Requested.Line = Locs[i].Line;
+ Requested.Column = Locs[i].Column;
+ FixItRewrite.addFixItLocation(Requested);
+ }
+
+ return true;
+}
+
+bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
+ llvm::StringRef Filename) {
+ Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
+ CI.getLangOpts()));
+ if (!AddFixItLocations(CI, *Rewriter))
+ return false;
+
+ return true;
+}
+
+void FixItAction::EndSourceFileAction() {
+ const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
+ Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile);
+}
+
+ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateObjCRewriter(InFile,
+ CI.createDefaultOutputFile(true, InFile, "cpp"),
+ CI.getDiagnostics(), CI.getLangOpts(),
+ CI.getDiagnosticOpts().NoRewriteMacros);
+}
+
+ASTConsumer *RewriteBlocksAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return CreateBlockRewriter(InFile, CI.getDiagnostics(), CI.getLangOpts());
+}
+
+ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ return new ASTConsumer();
+}
+
+CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {}
+
+ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ BackendAction BA = static_cast<BackendAction>(Act);
+ llvm::OwningPtr<llvm::raw_ostream> OS;
+ if (BA == Backend_EmitAssembly)
+ OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
+ else if (BA == Backend_EmitLL)
+ OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
+ else if (BA == Backend_EmitBC)
+ OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
+
+ return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(),
+ CI.getCodeGenOpts(), CI.getTargetOpts(), InFile,
+ OS.take(), CI.getLLVMContext());
+}
+
+EmitAssemblyAction::EmitAssemblyAction()
+ : CodeGenAction(Backend_EmitAssembly) {}
+
+EmitBCAction::EmitBCAction() : CodeGenAction(Backend_EmitBC) {}
+
+EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {}
+
+EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {}
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+void DumpRawTokensAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ SourceManager &SM = PP.getSourceManager();
+
+ // Start lexing the specified input file.
+ Lexer RawLex(SM.getMainFileID(), SM, PP.getLangOptions());
+ RawLex.SetKeepWhitespaceMode(true);
+
+ Token RawTok;
+ RawLex.LexFromRawLexer(RawTok);
+ while (RawTok.isNot(tok::eof)) {
+ PP.DumpToken(RawTok, true);
+ fprintf(stderr, "\n");
+ RawLex.LexFromRawLexer(RawTok);
+ }
+}
+
+void DumpTokensAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ // Start preprocessing the specified input file.
+ Token Tok;
+ PP.EnterMainSourceFile();
+ do {
+ PP.Lex(Tok);
+ PP.DumpToken(Tok, true);
+ fprintf(stderr, "\n");
+ } while (Tok.isNot(tok::eof));
+}
+
+void GeneratePTHAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ if (CI.getFrontendOpts().OutputFile.empty() ||
+ CI.getFrontendOpts().OutputFile == "-") {
+ // FIXME: Don't fail this way.
+ // FIXME: Verify that we can actually seek in the given file.
+ llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
+ ::exit(1);
+ }
+ llvm::raw_fd_ostream *OS =
+ CI.createDefaultOutputFile(true, getCurrentFile());
+ CacheTokens(CI.getPreprocessor(), OS);
+}
+
+void ParseOnlyAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ llvm::OwningPtr<Action> PA(new MinimalAction(PP));
+
+ Parser P(PP, *PA);
+ PP.EnterMainSourceFile();
+ P.ParseTranslationUnit();
+}
+
+void PreprocessOnlyAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+
+ Token Tok;
+ // Start parsing the specified input file.
+ PP.EnterMainSourceFile();
+ do {
+ PP.Lex(Tok);
+ } while (Tok.isNot(tok::eof));
+}
+
+void PrintParseAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
+
+ Parser P(PP, *PA);
+ PP.EnterMainSourceFile();
+ P.ParseTranslationUnit();
+}
+
+void PrintPreprocessedAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
+ CI.getPreprocessorOutputOpts());
+}
+
+void RewriteMacrosAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
+ RewriteMacrosInInput(CI.getPreprocessor(), OS);
+}
+
+void RewriteTestAction::ExecuteAction() {
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
+ DoRewriteTest(CI.getPreprocessor(), OS);
+}
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
new file mode 100644
index 000000000000..bd916386056b
--- /dev/null
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -0,0 +1,31 @@
+//===--- FrontendOptions.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/StringSwitch.h"
+using namespace clang;
+
+FrontendOptions::InputKind
+FrontendOptions::getInputKindForExtension(llvm::StringRef Extension) {
+ return llvm::StringSwitch<InputKind>(Extension)
+ .Case("ast", IK_AST)
+ .Case("c", IK_C)
+ .Cases("S", "s", IK_Asm)
+ .Case("i", IK_PreprocessedC)
+ .Case("ii", IK_PreprocessedCXX)
+ .Case("m", IK_ObjC)
+ .Case("mi", IK_PreprocessedObjC)
+ .Cases("mm", "M", IK_ObjCXX)
+ .Case("mii", IK_PreprocessedObjCXX)
+ .Case("C", IK_CXX)
+ .Cases("C", "cc", "cp", IK_CXX)
+ .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX)
+ .Case("cl", IK_OpenCL)
+ .Default(IK_C);
+}
diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp
index 145d53f3fc6e..3ba7abf38168 100644
--- a/lib/Frontend/HTMLDiagnostics.cpp
+++ b/lib/Frontend/HTMLDiagnostics.cpp
@@ -109,6 +109,8 @@ HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
ReportDiag(*D, FilesMade);
delete D;
}
+
+ BatchedDiags.clear();
}
void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index c0b4ebaab03b..d19ae9861ed6 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -11,12 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/InitHeaderSearch.h"
-#include "clang/Lex/HeaderSearch.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Frontend/HeaderSearchOptions.h"
+#include "clang/Lex/HeaderSearch.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/Config/config.h"
@@ -26,6 +30,66 @@
#include <windows.h>
#endif
using namespace clang;
+using namespace clang::frontend;
+
+namespace {
+
+/// InitHeaderSearch - This class makes it easier to set the search paths of
+/// a HeaderSearch object. InitHeaderSearch stores several search path lists
+/// internally, which can be sent to a HeaderSearch object in one swoop.
+class InitHeaderSearch {
+ std::vector<DirectoryLookup> IncludeGroup[4];
+ HeaderSearch& Headers;
+ bool Verbose;
+ std::string isysroot;
+
+public:
+
+ InitHeaderSearch(HeaderSearch &HS,
+ bool verbose = false, const std::string &iSysroot = "")
+ : Headers(HS), Verbose(verbose), isysroot(iSysroot) {}
+
+ /// AddPath - Add the specified path to the specified group list.
+ void AddPath(const llvm::StringRef &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,
+ 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);
+
+ /// 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);
+
+ // AddDefaultCIncludePaths - Add paths that should always be searched.
+ void AddDefaultCIncludePaths(const llvm::Triple &triple);
+
+ // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when
+ // compiling c++.
+ void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple);
+
+ /// AddDefaultSystemIncludePaths - Adds the default system include paths so
+ /// that e.g. stdio.h is found.
+ void AddDefaultSystemIncludePaths(const LangOptions &Lang,
+ const llvm::Triple &triple);
+
+ /// Realize - Merges all search path lists into one list and send it to
+ /// HeaderSearch.
+ void Realize();
+};
+
+}
void InitHeaderSearch::AddPath(const llvm::StringRef &Path,
IncludeDirGroup Group, bool isCXXAware,
@@ -82,9 +146,8 @@ void InitHeaderSearch::AddPath(const llvm::StringRef &Path,
}
-void InitHeaderSearch::AddEnvVarPaths(const char *Name) {
- const char* at = getenv(Name);
- if (!at || *at == 0) // Empty string should not add '.' path.
+void InitHeaderSearch::AddDelimitedPaths(const char *at) {
+ if (*at == 0) // Empty string should not add '.' path.
return;
const char* delim = strchr(at, llvm::sys::PathSeparator);
@@ -103,27 +166,30 @@ void InitHeaderSearch::AddEnvVarPaths(const char *Name) {
}
void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base,
+ const char *ArchDir,
const char *Dir32,
const char *Dir64,
const llvm::Triple &triple) {
+ // Add the common dirs
+ AddPath(Base, System, true, false, false);
+ AddPath(Base + "/backward", System, true, false, false);
+
+ // Add the multilib dirs
llvm::Triple::ArchType arch = triple.getArch();
bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64;
-
- AddPath(Base, System, true, false, false);
if (is64bit)
- AddPath(Base + "/" + Dir64, System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false);
else
- AddPath(Base + "/" + Dir32, System, true, false, false);
- AddPath(Base + "/backward", System, true, false, false);
+ AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false);
}
void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base,
const char *Arch,
const char *Version) {
- std::string localBase = Base + "/" + Arch + "/" + Version + "/include";
- AddPath(localBase, System, true, false, false);
- AddPath(localBase + "/c++", System, true, false, false);
- AddPath(localBase + "/c++/backward", System, true, false, false);
+ std::string localBase = Base + "/" + Arch + "/" + Version + "/include";
+ AddPath(localBase, System, true, false, false);
+ AddPath(localBase + "/c++", System, true, false, false);
+ AddPath(localBase + "/c++/backward", System, true, false, false);
}
// FIXME: This probably should goto to some platform utils place.
@@ -243,6 +309,16 @@ bool getVisualStudioDir(std::string &path) {
void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
// FIXME: temporary hack: hard-coded paths.
+ llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ llvm::SmallVector<llvm::StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin();
+ i != dirs.end();
+ ++i)
+ AddPath(*i, System, false, false, false);
+ return;
+ }
llvm::Triple::OSType os = triple.getOS();
switch (os) {
case llvm::Triple::Win32:
@@ -288,6 +364,17 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) {
void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
llvm::Triple::OSType os = triple.getOS();
+ llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT);
+ if (CxxIncludeRoot != "") {
+ llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH);
+ if (CxxIncludeArch == "")
+ AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(),
+ CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
+ else
+ AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH,
+ CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple);
+ return;
+ }
// FIXME: temporary hack: hard-coded paths.
switch (os) {
case llvm::Triple::Cygwin:
@@ -310,113 +397,77 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
break;
case llvm::Triple::Darwin:
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
- "i686-apple-darwin10",
- "i686-apple-darwin10/x86_64",
- triple);
+ "i686-apple-darwin10", "", "x86_64", triple);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0",
- "i686-apple-darwin8",
- "i686-apple-darwin8",
- triple);
+ "i686-apple-darwin8", "", "", triple);
break;
case llvm::Triple::Linux:
// Ubuntu 7.10 - Gutsy Gibbon
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
+ "i486-linux-gnu", "", "", triple);
// Ubuntu 9.04
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3",
- "x86_64-linux-gnu/32",
- "x86_64-linux-gnu",
- triple);
+ "x86_64-linux-gnu","32", "", triple);
+ // Ubuntu 9.10
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+ "x86_64-linux-gnu", "32", "", triple);
// Fedora 8
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
+ "i386-redhat-linux", "", "", triple);
// Fedora 9
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
+ "i386-redhat-linux", "", "", triple);
// Fedora 10
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2",
- "i386-redhat-linux",
- "i386-redhat-linux",
- triple);
+ "i386-redhat-linux","", "", triple);
+
+ // Fedora 11
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1",
+ "i586-redhat-linux","", "", triple);
+
// openSUSE 11.1 32 bit
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
+ "i586-suse-linux", "", "", triple);
// openSUSE 11.1 64 bit
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "x86_64-suse-linux/32",
- "x86_64-suse-linux",
- triple);
+ "x86_64-suse-linux", "32", "", triple);
// openSUSE 11.2
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "i586-suse-linux",
- "i586-suse-linux",
- triple);
+ "i586-suse-linux", "", "", triple);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4",
- "x86_64-suse-linux",
- "x86_64-suse-linux",
- triple);
+ "x86_64-suse-linux", "", "", triple);
// Arch Linux 2008-06-24
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "i686-pc-linux-gnu", "", "", triple);
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1",
- "x86_64-unknown-linux-gnu",
- "x86_64-unknown-linux-gnu",
- triple);
+ "x86_64-unknown-linux-gnu", "", "", triple);
// Gentoo x86 2009.1 stable
AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
// Gentoo x86 2009.0 stable
AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
// Gentoo x86 2008.0 stable
AddGnuCPlusPlusIncludePaths(
- "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4",
+ "i686-pc-linux-gnu", "", "", triple);
// Ubuntu 8.10
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-pc-linux-gnu",
- "i486-pc-linux-gnu",
- triple);
+ "i486-pc-linux-gnu", "", "", triple);
// Ubuntu 9.04
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3",
- "i486-linux-gnu",
- "i486-linux-gnu",
- triple);
+ "i486-linux-gnu","", "", triple);
// Gentoo amd64 stable
AddGnuCPlusPlusIncludePaths(
"/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ "i686-pc-linux-gnu", "", "", triple);
// Exherbo (2009-10-26)
- AddGnuCPlusPlusIncludePaths(
- "/usr/include/c++/4.4.2",
- "x86_64-pc-linux-gnu/32",
- "x86_64-pc-linux-gnu",
- triple);
- AddGnuCPlusPlusIncludePaths(
- "/usr/include/c++/4.4.2",
- "i686-pc-linux-gnu",
- "i686-pc-linux-gnu",
- triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+ "x86_64-pc-linux-gnu", "32", "", triple);
+ AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2",
+ "i686-pc-linux-gnu", "", "", triple);
break;
case llvm::Triple::FreeBSD:
// DragonFly
@@ -429,44 +480,27 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl
case llvm::Triple::AuroraUX:
// AuroraUX
AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
- "i386-pc-solaris2.11",
- "i386-pc-solaris2.11",
- triple);
+ "i386-pc-solaris2.11", "", "", triple);
break;
default:
break;
}
}
-void InitHeaderSearch::AddDefaultFrameworkIncludePaths(const llvm::Triple &triple) {
- llvm::Triple::OSType os = triple.getOS();
- if (os != llvm::Triple::Darwin)
- return;
- AddPath("/System/Library/Frameworks", System, true, false, true);
- AddPath("/Library/Frameworks", System, true, false, true);
-}
-
void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,
const llvm::Triple &triple) {
AddDefaultCIncludePaths(triple);
- AddDefaultFrameworkIncludePaths(triple);
+
+ // Add the default framework include paths on Darwin.
+ if (triple.getOS() == llvm::Triple::Darwin) {
+ AddPath("/System/Library/Frameworks", System, true, false, true);
+ AddPath("/Library/Frameworks", System, true, false, true);
+ }
+
if (Lang.CPlusPlus)
AddDefaultCPlusPlusIncludePaths(triple);
}
-void InitHeaderSearch::AddDefaultEnvVarPaths(const LangOptions &Lang) {
- AddEnvVarPaths("CPATH");
- if (Lang.CPlusPlus && Lang.ObjC1)
- AddEnvVarPaths("OBJCPLUS_INCLUDE_PATH");
- else if (Lang.CPlusPlus)
- AddEnvVarPaths("CPLUS_INCLUDE_PATH");
- else if (Lang.ObjC1)
- AddEnvVarPaths("OBJC_INCLUDE_PATH");
- else
- AddEnvVarPaths("C_INCLUDE_PATH");
-}
-
-
/// RemoveDuplicates - If there are duplicate directory entries in the specified
/// search list, remove the later (dead) ones.
static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
@@ -591,3 +625,40 @@ void InitHeaderSearch::Realize() {
fprintf(stderr, "End of search list.\n");
}
}
+
+void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
+ const HeaderSearchOptions &HSOpts,
+ const LangOptions &Lang,
+ const llvm::Triple &Triple) {
+ InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
+
+ // Add the user defined entries.
+ for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
+ const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i];
+ Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework,
+ false);
+ }
+
+ // Add entries from CPATH and friends.
+ Init.AddDelimitedPaths(HSOpts.EnvIncPath.c_str());
+ if (Lang.CPlusPlus && Lang.ObjC1)
+ Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath.c_str());
+ else if (Lang.CPlusPlus)
+ Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath.c_str());
+ else if (Lang.ObjC1)
+ Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath.c_str());
+ else
+ Init.AddDelimitedPaths(HSOpts.CEnvIncPath.c_str());
+
+ if (!HSOpts.BuiltinIncludePath.empty()) {
+ // Ignore the sys root, we *always* look for clang headers relative to
+ // supplied path.
+ Init.AddPath(HSOpts.BuiltinIncludePath, System,
+ false, false, false, /*IgnoreSysRoot=*/ true);
+ }
+
+ if (HSOpts.UseStandardIncludes)
+ Init.AddDefaultSystemIncludePaths(Lang, Triple);
+
+ Init.Realize();
+}
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 7139e55f0b60..4ee286dd265d 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -11,8 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/InitPreprocessor.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/PreprocessorOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
@@ -60,9 +61,7 @@ static void UndefineBuiltinMacro(std::vector<char> &Buf, const char *Macro) {
Buf.push_back('\n');
}
-/// Add the quoted name of an implicit include file.
-static void AddQuotedIncludePath(std::vector<char> &Buf,
- const std::string &File) {
+std::string clang::NormalizeDashIncludePath(llvm::StringRef File) {
// Implicit include paths should be resolved relative to the current
// working directory first, and then use the regular header search
// mechanism. The proper way to handle this is to have the
@@ -75,9 +74,16 @@ static void AddQuotedIncludePath(std::vector<char> &Buf,
if (!Path.exists())
Path = File;
+ return Lexer::Stringify(Path.str());
+}
+
+/// Add the quoted name of an implicit include file.
+static void AddQuotedIncludePath(std::vector<char> &Buf,
+ const std::string &File) {
+
// Escape double quotes etc.
Buf.push_back('"');
- std::string EscapedFile = Lexer::Stringify(Path.str());
+ std::string EscapedFile = NormalizeDashIncludePath(File);
Buf.insert(Buf.end(), EscapedFile.begin(), EscapedFile.end());
Buf.push_back('"');
}
@@ -216,6 +222,14 @@ static void DefineTypeSize(const char *MacroName, unsigned TypeWidth,
DefineBuiltinMacro(Buf, MacroBuf);
}
+/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
+/// the width, suffix, and signedness of the given type
+static void DefineTypeSize(const char *MacroName, TargetInfo::IntType Ty,
+ const TargetInfo &TI, std::vector<char> &Buf) {
+ DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty),
+ TI.isTypeSigned(Ty), Buf);
+}
+
static void DefineType(const char *MacroName, TargetInfo::IntType Ty,
std::vector<char> &Buf) {
char MacroBuf[60];
@@ -223,6 +237,20 @@ static void DefineType(const char *MacroName, TargetInfo::IntType Ty,
DefineBuiltinMacro(Buf, MacroBuf);
}
+static void DefineExactWidthIntType(TargetInfo::IntType Ty,
+ const TargetInfo &TI, std::vector<char> &Buf) {
+ char MacroBuf[60];
+ int TypeWidth = TI.getTypeWidth(Ty);
+ sprintf(MacroBuf, "__INT%d_TYPE__", TypeWidth);
+ DefineType(MacroBuf, Ty, Buf);
+
+
+ const char *ConstSuffix = TargetInfo::getTypeConstantSuffix(Ty);
+ if (strlen(ConstSuffix) > 0) {
+ sprintf(MacroBuf, "__INT%d_C_SUFFIX__=%s", TypeWidth, ConstSuffix);
+ DefineBuiltinMacro(Buf, MacroBuf);
+ }
+}
static void InitializePredefinedMacros(const TargetInfo &TI,
const LangOptions &LangOpts,
@@ -346,14 +374,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineBuiltinMacro(Buf, "__CHAR_BIT__=8");
DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Buf);
- DefineTypeSize("__SHRT_MAX__", TI.getShortWidth(), "", true, Buf);
- DefineTypeSize("__INT_MAX__", TI.getIntWidth(), "", true, Buf);
- DefineTypeSize("__LONG_MAX__", TI.getLongWidth(), "L", true, Buf);
- DefineTypeSize("__LONG_LONG_MAX__", TI.getLongLongWidth(), "LL", true, Buf);
- DefineTypeSize("__WCHAR_MAX__", TI.getWCharWidth(), "", true, Buf);
- TargetInfo::IntType IntMaxType = TI.getIntMaxType();
- DefineTypeSize("__INTMAX_MAX__", TI.getTypeWidth(IntMaxType),
- TI.getTypeConstantSuffix(IntMaxType), true, Buf);
+ DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Buf);
+ DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Buf);
+ DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Buf);
+ DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Buf);
+ DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Buf);
+ DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Buf);
DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Buf);
DefineType("__UINTMAX_TYPE__", TI.getUIntMaxType(), Buf);
@@ -374,23 +400,22 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (!LangOpts.CharIsSigned)
DefineBuiltinMacro(Buf, "__CHAR_UNSIGNED__");
- // Define fixed-sized integer types for stdint.h
- assert(TI.getCharWidth() == 8 && "unsupported target types");
- assert(TI.getShortWidth() == 16 && "unsupported target types");
- DefineBuiltinMacro(Buf, "__INT8_TYPE__=char");
- DefineBuiltinMacro(Buf, "__INT16_TYPE__=short");
-
- if (TI.getIntWidth() == 32)
- DefineBuiltinMacro(Buf, "__INT32_TYPE__=int");
- else {
- assert(TI.getLongLongWidth() == 32 && "unsupported target types");
- DefineBuiltinMacro(Buf, "__INT32_TYPE__=long long");
- }
-
- // 16-bit targets doesn't necessarily have a 64-bit type.
- if (TI.getLongLongWidth() == 64)
- DefineType("__INT64_TYPE__", TI.getInt64Type(), Buf);
+ // Define exact-width integer types for stdint.h
+ sprintf(MacroBuf, "__INT%d_TYPE__=char", TI.getCharWidth());
+ DefineBuiltinMacro(Buf, MacroBuf);
+ if (TI.getShortWidth() > TI.getCharWidth())
+ DefineExactWidthIntType(TargetInfo::SignedShort, TI, Buf);
+
+ if (TI.getIntWidth() > TI.getShortWidth())
+ DefineExactWidthIntType(TargetInfo::SignedInt, TI, Buf);
+
+ if (TI.getLongWidth() > TI.getIntWidth())
+ DefineExactWidthIntType(TargetInfo::SignedLong, TI, Buf);
+
+ if (TI.getLongLongWidth() > TI.getLongWidth())
+ DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Buf);
+
// Add __builtin_va_list typedef.
{
const char *VAList = TI.getVAListDeclaration();
@@ -443,7 +468,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
/// environment ready to process a single file. This returns true on error.
///
void clang::InitializePreprocessor(Preprocessor &PP,
- const PreprocessorInitOptions &InitOpts) {
+ const PreprocessorOptions &InitOpts,
+ const HeaderSearchOptions &HSOpts) {
std::vector<char> PredefineBuffer;
const char *LineDirective = "# 1 \"<built-in>\" 3\n";
@@ -451,7 +477,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Install things like __POWERPC__, __GNUC__, etc into the macro table.
- if (InitOpts.getUsePredefines())
+ if (InitOpts.UsePredefines)
InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
PredefineBuffer);
@@ -462,30 +488,33 @@ void clang::InitializePreprocessor(Preprocessor &PP,
LineDirective, LineDirective+strlen(LineDirective));
// Process #define's and #undef's in the order they are given.
- for (PreprocessorInitOptions::macro_iterator I = InitOpts.macro_begin(),
- E = InitOpts.macro_end(); I != E; ++I) {
- if (I->second) // isUndef
- UndefineBuiltinMacro(PredefineBuffer, I->first.c_str());
+ for (unsigned i = 0, e = InitOpts.Macros.size(); i != e; ++i) {
+ if (InitOpts.Macros[i].second) // isUndef
+ UndefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str());
else
- DefineBuiltinMacro(PredefineBuffer, I->first.c_str());
+ DefineBuiltinMacro(PredefineBuffer, InitOpts.Macros[i].first.c_str());
}
// If -imacros are specified, include them now. These are processed before
// any -include directives.
- for (PreprocessorInitOptions::imacro_iterator I = InitOpts.imacro_begin(),
- E = InitOpts.imacro_end(); I != E; ++I)
- AddImplicitIncludeMacros(PredefineBuffer, *I);
+ for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
+ AddImplicitIncludeMacros(PredefineBuffer, InitOpts.MacroIncludes[i]);
// Process -include directives.
- for (PreprocessorInitOptions::include_iterator I = InitOpts.include_begin(),
- E = InitOpts.include_end(); I != E; ++I) {
- if (I->second) // isPTH
- AddImplicitIncludePTH(PredefineBuffer, PP, I->first);
+ for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
+ const std::string &Path = InitOpts.Includes[i];
+ if (Path == InitOpts.ImplicitPTHInclude)
+ AddImplicitIncludePTH(PredefineBuffer, PP, Path);
else
- AddImplicitInclude(PredefineBuffer, I->first);
+ AddImplicitInclude(PredefineBuffer, Path);
}
// Null terminate PredefinedBuffer and add it.
PredefineBuffer.push_back(0);
PP.setPredefines(&PredefineBuffer[0]);
+
+ // Initialize the header search object.
+ ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), HSOpts,
+ PP.getLangOptions(),
+ PP.getTargetInfo().getTriple());
}
diff --git a/lib/Frontend/ManagerRegistry.cpp b/lib/Frontend/ManagerRegistry.cpp
deleted file mode 100644
index 79f1e8178e10..000000000000
--- a/lib/Frontend/ManagerRegistry.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-//===- ManagerRegistry.cpp - Pluggble Analyzer module creators --*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the pluggable analyzer module creators.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/ManagerRegistry.h"
-
-using namespace clang;
-
-StoreManagerCreator ManagerRegistry::StoreMgrCreator = 0;
-
-ConstraintManagerCreator ManagerRegistry::ConstraintMgrCreator = 0;
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 26f426ba329b..ca7aa3260c62 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -13,6 +13,7 @@
#include "clang/Frontend/PCHReader.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -104,6 +105,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
+ PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
Reader.Diag(diag::warn_pch_gc_mode)
<< LangOpts.getGCMode() << PPLangOpts.getGCMode();
@@ -121,83 +123,56 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
return false;
}
-bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
- if (Triple != PP.getTargetInfo().getTriple().getTriple()) {
- Reader.Diag(diag::warn_pch_target_triple)
- << Triple << PP.getTargetInfo().getTriple().getTriple();
- return true;
- }
- return false;
-}
-
-/// \brief Split the given string into a vector of lines, eliminating
-/// any empty lines in the process.
-///
-/// \param Str the string to split.
-/// \param Len the length of Str.
-/// \param KeepEmptyLines true if empty lines should be included
-/// \returns a vector of lines, with the line endings removed
-static std::vector<std::string> splitLines(const char *Str, unsigned Len,
- bool KeepEmptyLines = false) {
- std::vector<std::string> Lines;
- for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
- unsigned LineEnd = LineStart;
- while (LineEnd < Len && Str[LineEnd] != '\n')
- ++LineEnd;
- if (LineStart != LineEnd || KeepEmptyLines)
- Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
- LineStart = LineEnd;
- }
- return Lines;
-}
-
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static bool startsWith(const std::string &Haystack, const char *Needle) {
- for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
- if (I == N)
- return false;
- if (Haystack[I] != Needle[I])
- return false;
- }
+bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
+ if (Triple == PP.getTargetInfo().getTriple().str())
+ return false;
+ Reader.Diag(diag::warn_pch_target_triple)
+ << Triple << PP.getTargetInfo().getTriple().str();
return true;
}
-/// \brief Determine whether the string Haystack starts with the
-/// substring Needle.
-static inline bool startsWith(const std::string &Haystack,
- const std::string &Needle) {
- return startsWith(Haystack, Needle.c_str());
-}
-
-bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID,
+ llvm::StringRef OriginalFileName,
std::string &SuggestedPredefines) {
- const char *Predef = PP.getPredefines().c_str();
- unsigned PredefLen = PP.getPredefines().size();
-
- // If the two predefines buffers compare equal, we're done!
- if (PredefLen == PCHPredefLen &&
- strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
+ // We are in the context of an implicit include, so the predefines buffer will
+ // have a #include entry for the PCH file itself (as normalized by the
+ // preprocessor initialization). Find it and skip over it in the checking
+ // below.
+ llvm::SmallString<256> PCHInclude;
+ PCHInclude += "#include \"";
+ PCHInclude += NormalizeDashIncludePath(OriginalFileName);
+ PCHInclude += "\"\n";
+ std::pair<llvm::StringRef,llvm::StringRef> Split =
+ llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
+ llvm::StringRef Left = Split.first, Right = Split.second;
+ assert(Left != PP.getPredefines() && "Missing PCH include entry!");
+
+ // If the predefines is equal to the joined left and right halves, we're done!
+ if (Left.size() + Right.size() == PCHPredef.size() &&
+ PCHPredef.startswith(Left) && PCHPredef.endswith(Right))
return false;
SourceManager &SourceMgr = PP.getSourceManager();
- // The predefines buffers are different. Determine what the
- // differences are, and whether they require us to reject the PCH
- // file.
- std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
- std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
+ // The predefines buffers are different. Determine what the differences are,
+ // and whether they require us to reject the PCH file.
+ llvm::SmallVector<llvm::StringRef, 8> PCHLines;
+ PCHPredef.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+ llvm::SmallVector<llvm::StringRef, 8> CmdLineLines;
+ Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ Right.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
- // Sort both sets of predefined buffer lines, since
+ // Sort both sets of predefined buffer lines, since we allow some extra
+ // definitions and they may appear at any point in the output.
std::sort(CmdLineLines.begin(), CmdLineLines.end());
std::sort(PCHLines.begin(), PCHLines.end());
- // Determine which predefines that where used to build the PCH file
- // are missing from the command line.
- std::vector<std::string> MissingPredefines;
+ // Determine which predefines that were used to build the PCH file are missing
+ // from the command line.
+ std::vector<llvm::StringRef> MissingPredefines;
std::set_difference(PCHLines.begin(), PCHLines.end(),
CmdLineLines.begin(), CmdLineLines.end(),
std::back_inserter(MissingPredefines));
@@ -205,31 +180,30 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
bool MissingDefines = false;
bool ConflictingDefines = false;
for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
- const std::string &Missing = MissingPredefines[I];
- if (!startsWith(Missing, "#define ") != 0) {
+ llvm::StringRef Missing = MissingPredefines[I];
+ if (!Missing.startswith("#define ")) {
Reader.Diag(diag::warn_pch_compiler_options_mismatch);
return true;
}
- // This is a macro definition. Determine the name of the macro
- // we're defining.
+ // This is a macro definition. Determine the name of the macro we're
+ // defining.
std::string::size_type StartOfMacroName = strlen("#define ");
std::string::size_type EndOfMacroName
= Missing.find_first_of("( \n\r", StartOfMacroName);
assert(EndOfMacroName != std::string::npos &&
"Couldn't find the end of the macro name");
- std::string MacroName = Missing.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
+ llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
- // Determine whether this macro was given a different definition
- // on the command line.
- std::string MacroDefStart = "#define " + MacroName;
+ // Determine whether this macro was given a different definition on the
+ // command line.
+ std::string MacroDefStart = "#define " + MacroName.str();
std::string::size_type MacroDefLen = MacroDefStart.size();
- std::vector<std::string>::iterator ConflictPos
+ llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos
= std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
MacroDefStart);
for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
- if (!startsWith(*ConflictPos, MacroDefStart)) {
+ if (!ConflictPos->startswith(MacroDefStart)) {
// Different macro; we're done.
ConflictPos = CmdLineLines.end();
break;
@@ -250,21 +224,18 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
<< MacroName;
// Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
- .getFileLocWithOffset(Offset);
- Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
- << MacroName;
+ llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+ assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ .getFileLocWithOffset(Offset);
+ Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
ConflictingDefines = true;
continue;
}
- // If the macro doesn't conflict, then we'll just pick up the
- // macro definition from the PCH file. Warn the user that they
- // made a mistake.
+ // If the macro doesn't conflict, then we'll just pick up the macro
+ // definition from the PCH file. Warn the user that they made a mistake.
if (ConflictingDefines)
continue; // Don't complain if there are already conflicting defs
@@ -274,10 +245,9 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
}
// Show the definition of this macro within the PCH file.
- const char *MissingDef = strstr(PCHPredef, Missing.c_str());
- unsigned Offset = MissingDef - PCHPredef;
- SourceLocation PCHMissingLoc
- = SourceMgr.getLocForStartOfFile(PCHBufferID)
+ llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
+ assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
+ SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
.getFileLocWithOffset(Offset);
Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
}
@@ -289,13 +259,13 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
// parameters that were not present when building the PCH
// file. Extra #defines are okay, so long as the identifiers being
// defined were not used within the precompiled header.
- std::vector<std::string> ExtraPredefines;
+ std::vector<llvm::StringRef> ExtraPredefines;
std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
PCHLines.begin(), PCHLines.end(),
std::back_inserter(ExtraPredefines));
for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
- const std::string &Extra = ExtraPredefines[I];
- if (!startsWith(Extra, "#define ") != 0) {
+ llvm::StringRef &Extra = ExtraPredefines[I];
+ if (!Extra.startswith("#define ")) {
Reader.Diag(diag::warn_pch_compiler_options_mismatch);
return true;
}
@@ -307,16 +277,13 @@ bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
= Extra.find_first_of("( \n\r", StartOfMacroName);
assert(EndOfMacroName != std::string::npos &&
"Couldn't find the end of the macro name");
- std::string MacroName = Extra.substr(StartOfMacroName,
- EndOfMacroName - StartOfMacroName);
+ llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
// Check whether this name was used somewhere in the PCH file. If
// so, defining it as a macro could change behavior, so we reject
// the PCH file.
- if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
- MacroName.c_str() + MacroName.size())) {
- Reader.Diag(diag::warn_macro_name_used_in_pch)
- << II;
+ if (IdentifierInfo *II = Reader.get(MacroName)) {
+ Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
return true;
}
@@ -650,11 +617,11 @@ bool PCHReader::Error(const char *Msg) {
///
/// \returns true if there was a mismatch (in which case the PCH file
/// should be ignored), or false otherwise.
-bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
- unsigned PCHPredefLen,
+bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef,
FileID PCHBufferID) {
if (Listener)
- return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
+ return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID,
+ ActualOriginalFileName,
SuggestedPredefines);
return false;
}
@@ -1364,7 +1331,8 @@ PCHReader::ReadPCHBlock() {
break;
case pch::ORIGINAL_FILE_NAME:
- OriginalFileName.assign(BlobStart, BlobLen);
+ ActualOriginalFileName.assign(BlobStart, BlobLen);
+ OriginalFileName = ActualOriginalFileName;
MaybeAddSystemRootToFilename(OriginalFileName);
break;
@@ -1403,10 +1371,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
//
// FIXME: This shouldn't be here, we should just take a raw_ostream.
std::string ErrStr;
- if (FileName == "-")
- Buffer.reset(llvm::MemoryBuffer::getSTDIN());
- else
- Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
+ Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
if (!Buffer) {
Error(ErrStr.c_str());
return IgnorePCH;
@@ -1478,7 +1443,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
}
// Check the predefines buffer.
- if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
+ if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen),
PCHPredefinesBufferID))
return IgnorePCH;
@@ -1741,6 +1706,7 @@ bool PCHReader::ParseLanguageOptions(
PARSE_LANGOPT(NoInline);
PARSE_LANGOPT(AccessControl);
PARSE_LANGOPT(CharIsSigned);
+ PARSE_LANGOPT(ShortWChar);
LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
++Idx;
LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
@@ -2213,6 +2179,14 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
return ReadDeclExpr();
case TemplateArgument::Type:
return GetDeclaratorInfo(Record, Index);
+ case TemplateArgument::Template: {
+ SourceLocation
+ QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
+ QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
+ TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
+ return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
+ TemplateNameLoc);
+ }
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index b9ece21f74c3..6a92a2db51a8 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -264,7 +264,12 @@ void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
ClassRefs.reserve(NumClassRefs);
for (unsigned I = 0; I != NumClassRefs; ++I)
ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
- CD->setClassList(*Reader.getContext(), ClassRefs.data(), NumClassRefs);
+ llvm::SmallVector<SourceLocation, 16> SLocs;
+ SLocs.reserve(NumClassRefs);
+ for (unsigned I = 0; I != NumClassRefs; ++I)
+ SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+ CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(),
+ NumClassRefs);
}
void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
@@ -442,6 +447,8 @@ Attr *PCHReader::ReadAttributes() {
(BlocksAttr::BlocksAttrTypes)Record[Idx++]);
break;
+ SIMPLE_ATTR(CDecl);
+
case Attr::Cleanup:
New = ::new (*Context) CleanupAttr(
cast<FunctionDecl>(GetDecl(Record[Idx++])));
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index de56166125ed..8a45ebce1b9d 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -765,6 +765,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
// be enabled.
Record.push_back(LangOpts.CharIsSigned); // Whether char is a signed or
// unsigned type
+ Record.push_back(LangOpts.ShortWChar); // force wchar_t to be unsigned short
Record.push_back(LangOpts.getGCMode());
Record.push_back(LangOpts.getVisibilityMode());
Record.push_back(LangOpts.getStackProtectorMode());
@@ -1247,9 +1248,9 @@ void PCHWriter::WriteType(QualType T) {
// Emit the type's representation.
PCHTypeWriter W(*this, Record);
- if (T.hasNonFastQualifiers()) {
- Qualifiers Qs = T.getQualifiers();
- AddTypeRef(T.getUnqualifiedType(), Record);
+ if (T.hasLocalNonFastQualifiers()) {
+ Qualifiers Qs = T.getLocalQualifiers();
+ AddTypeRef(T.getLocalUnqualifiedType(), Record);
Record.push_back(Qs.getAsOpaqueValue());
W.Code = pch::TYPE_EXT_QUAL;
} else {
@@ -1767,6 +1768,9 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
break;
+ case Attr::CDecl:
+ break;
+
case Attr::Cleanup:
AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
break;
@@ -2118,6 +2122,12 @@ void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
case TemplateArgument::Type:
AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record);
break;
+ case TemplateArgument::Template:
+ Record.push_back(
+ Arg.getTemplateQualifierRange().getBegin().getRawEncoding());
+ Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding());
+ Record.push_back(Arg.getTemplateNameLoc().getRawEncoding());
+ break;
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
@@ -2144,10 +2154,10 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
return;
}
- unsigned FastQuals = T.getFastQualifiers();
+ unsigned FastQuals = T.getLocalFastQualifiers();
T.removeFastQualifiers();
- if (T.hasNonFastQualifiers()) {
+ if (T.hasLocalNonFastQualifiers()) {
pch::TypeID &ID = TypeIDs[T];
if (ID == 0) {
// We haven't seen these qualifiers applied to this type before.
@@ -2162,7 +2172,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
return;
}
- assert(!T.hasQualifiers());
+ assert(!T.hasLocalQualifiers());
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
pch::TypeID ID = 0;
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 8997e661a5a1..c7bfee2c8bcd 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -260,7 +260,9 @@ void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
VisitDecl(D);
Record.push_back(D->size());
for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
- Writer.AddDeclRef(*I, Record);
+ Writer.AddDeclRef(I->getInterface(), Record);
+ for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
+ Writer.AddSourceLocation(I->getLocation(), Record);
Code = pch::DECL_OBJC_CLASS;
}
diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp
index 1be9ea8b8c41..6bcf39a92a24 100644
--- a/lib/Frontend/PlistDiagnostics.cpp
+++ b/lib/Frontend/PlistDiagnostics.cpp
@@ -37,6 +37,7 @@ namespace {
const std::string OutputFile;
const LangOptions &LangOpts;
llvm::OwningPtr<PathDiagnosticClient> SubPD;
+ bool flushed;
public:
PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
PathDiagnosticClient *subPD);
@@ -61,7 +62,7 @@ namespace {
PlistDiagnostics::PlistDiagnostics(const std::string& output,
const LangOptions &LO,
PathDiagnosticClient *subPD)
- : OutputFile(output), LangOpts(LO), SubPD(subPD) {}
+ : OutputFile(output), LangOpts(LO), SubPD(subPD), flushed(false) {}
PathDiagnosticClient*
clang::CreatePlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
@@ -310,6 +311,11 @@ void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
*FilesMade) {
+
+ if (flushed)
+ return;
+
+ flushed = true;
// Build up a set of FIDs that we use by scanning the locations and
// ranges of the diagnostics.
@@ -423,4 +429,6 @@ void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
if (FilesMade)
FilesMade->push_back(OutputFile);
+
+ BatchedDiags.clear();
}
diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp
index 25b40c78183c..deb5498b906e 100644
--- a/lib/Frontend/PrintParserCallbacks.cpp
+++ b/lib/Frontend/PrintParserCallbacks.cpp
@@ -79,10 +79,11 @@ namespace {
/// Scope will always be top level file scope.
Action::DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
unsigned NumElts) {
Out << __FUNCTION__ << "\n";
return MinimalAction::ActOnForwardClassDeclaration(AtClassLoc, IdentList,
- NumElts);
+ IdentLocs, NumElts);
}
// Pure Printing
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 630a093a4bf6..37424057809c 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -13,13 +13,14 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/Utils.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Pragma.h"
+#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/TokenConcatenation.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
@@ -439,7 +440,7 @@ namespace {
};
}
-void clang::DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
+static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
// -dM mode just scans and ignores all tokens in the files, then dumps out
// the macro table at the end.
PP.EnterMainSourceFile();
@@ -467,18 +468,23 @@ void clang::DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
/// DoPrintPreprocessedInput - This implements -E mode.
///
void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
- bool EnableCommentOutput,
- bool EnableMacroCommentOutput,
- bool DisableLineMarkers,
- bool DumpDefines) {
+ const PreprocessorOutputOptions &Opts) {
+ // Show macros with no output is handled specially.
+ if (!Opts.ShowCPP) {
+ assert(Opts.ShowMacros && "Not yet implemented!");
+ DoPrintMacros(PP, OS);
+ return;
+ }
+
// Inform the preprocessor whether we want it to retain comments or not, due
// to -C or -CC.
- PP.SetCommentRetentionState(EnableCommentOutput, EnableMacroCommentOutput);
+ PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
OS->SetBufferSize(64*1024);
PrintPPOutputPPCallbacks *Callbacks =
- new PrintPPOutputPPCallbacks(PP, *OS, DisableLineMarkers, DumpDefines);
+ new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
+ Opts.ShowMacros);
PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
Callbacks));
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 24ad69e3e0d3..06955e5c30b6 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -744,7 +744,7 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
typedefString += "\n";
for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
I != E; ++I) {
- ObjCInterfaceDecl *ForwardDecl = *I;
+ ObjCInterfaceDecl *ForwardDecl = I->getInterface();
typedefString += "#ifndef _REWRITER_typedef_";
typedefString += ForwardDecl->getNameAsString();
typedefString += "\n";
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 4f8c804844b0..6ab0e1605276 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -39,9 +39,16 @@ static const enum llvm::raw_ostream::Colors savedColor =
const unsigned WordWrapIndentation = 6;
TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream &os,
- const DiagnosticOptions &diags)
+ const DiagnosticOptions &diags,
+ bool _OwnsOutputStream)
: OS(os), LangOpts(0), DiagOpts(&diags),
- LastCaretDiagnosticWasNote(false) {
+ LastCaretDiagnosticWasNote(0),
+ OwnsOutputStream(_OwnsOutputStream) {
+}
+
+TextDiagnosticPrinter::~TextDiagnosticPrinter() {
+ if (OwnsOutputStream)
+ delete &OS;
}
void TextDiagnosticPrinter::
diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp
new file mode 100644
index 000000000000..2891aec50444
--- /dev/null
+++ b/lib/Frontend/VerifyDiagnosticsClient.cpp
@@ -0,0 +1,344 @@
+//===--- VerifyDiagnosticsClient.cpp - Verifying Diagnostic Client --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+VerifyDiagnosticsClient::VerifyDiagnosticsClient(Diagnostic &_Diags,
+ DiagnosticClient *_Primary)
+ : Diags(_Diags), PrimaryClient(_Primary),
+ Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0), NumErrors(0) {
+}
+
+VerifyDiagnosticsClient::~VerifyDiagnosticsClient() {
+ CheckDiagnostics();
+}
+
+// DiagnosticClient interface.
+
+void VerifyDiagnosticsClient::BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP) {
+ // FIXME: Const hack, we screw up the preprocessor but in practice its ok
+ // because it doesn't get reused. It would be better if we could make a copy
+ // though.
+ CurrentPreprocessor = const_cast<Preprocessor*>(PP);
+
+ PrimaryClient->BeginSourceFile(LangOpts, PP);
+}
+
+void VerifyDiagnosticsClient::EndSourceFile() {
+ CheckDiagnostics();
+
+ PrimaryClient->EndSourceFile();
+
+ CurrentPreprocessor = 0;
+}
+
+void VerifyDiagnosticsClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+ const DiagnosticInfo &Info) {
+ // Send the diagnostic to the buffer, we will check it once we reach the end
+ // of the source file (or are destructed).
+ Buffer->HandleDiagnostic(DiagLevel, Info);
+}
+
+// FIXME: It would be nice to just get this from the primary diagnostic client
+// or something.
+bool VerifyDiagnosticsClient::HadErrors() {
+ CheckDiagnostics();
+
+ return NumErrors != 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Checking diagnostics implementation.
+//===----------------------------------------------------------------------===//
+
+typedef TextDiagnosticBuffer::DiagList DiagList;
+typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+
+/// FindDiagnostics - Go through the comment and see if it indicates expected
+/// diagnostics. If so, then put them in a diagnostic list.
+///
+static void FindDiagnostics(const char *CommentStart, unsigned CommentLen,
+ DiagList &ExpectedDiags,
+ Preprocessor &PP, SourceLocation Pos,
+ const char *ExpectedStr) {
+ const char *CommentEnd = CommentStart+CommentLen;
+ unsigned ExpectedStrLen = strlen(ExpectedStr);
+
+ // Find all expected-foo diagnostics in the string and add them to
+ // ExpectedDiags.
+ while (CommentStart != CommentEnd) {
+ CommentStart = std::find(CommentStart, CommentEnd, 'e');
+ if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return;
+
+ // If this isn't expected-foo, ignore it.
+ if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) {
+ ++CommentStart;
+ continue;
+ }
+
+ CommentStart += ExpectedStrLen;
+
+ // Skip whitespace.
+ while (CommentStart != CommentEnd &&
+ isspace(CommentStart[0]))
+ ++CommentStart;
+
+ // Default, if we find the '{' now, is 1 time.
+ int Times = 1;
+ int Temp = 0;
+ // In extended syntax, there could be a digit now.
+ while (CommentStart != CommentEnd &&
+ CommentStart[0] >= '0' && CommentStart[0] <= '9') {
+ Temp *= 10;
+ Temp += CommentStart[0] - '0';
+ ++CommentStart;
+ }
+ if (Temp > 0)
+ Times = Temp;
+
+ // Skip whitespace again.
+ while (CommentStart != CommentEnd &&
+ isspace(CommentStart[0]))
+ ++CommentStart;
+
+ // We should have a {{ now.
+ if (CommentEnd-CommentStart < 2 ||
+ CommentStart[0] != '{' || CommentStart[1] != '{') {
+ if (std::find(CommentStart, CommentEnd, '{') != CommentEnd)
+ PP.Diag(Pos, diag::err_verify_bogus_characters);
+ else
+ PP.Diag(Pos, diag::err_verify_missing_start);
+ return;
+ }
+ CommentStart += 2;
+
+ // Find the }}.
+ const char *ExpectedEnd = CommentStart;
+ while (1) {
+ ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}');
+ if (CommentEnd-ExpectedEnd < 2) {
+ PP.Diag(Pos, diag::err_verify_missing_end);
+ return;
+ }
+
+ if (ExpectedEnd[1] == '}')
+ break;
+
+ ++ExpectedEnd; // Skip over singular }'s
+ }
+
+ std::string Msg(CommentStart, ExpectedEnd);
+ std::string::size_type FindPos;
+ while ((FindPos = Msg.find("\\n")) != std::string::npos)
+ Msg.replace(FindPos, 2, "\n");
+ // Add is possibly multiple times.
+ for (int i = 0; i < Times; ++i)
+ ExpectedDiags.push_back(std::make_pair(Pos, Msg));
+
+ CommentStart = ExpectedEnd;
+ }
+}
+
+/// FindExpectedDiags - Lex the main source file to find all of the
+// expected errors and warnings.
+static void FindExpectedDiags(Preprocessor &PP,
+ DiagList &ExpectedErrors,
+ DiagList &ExpectedWarnings,
+ DiagList &ExpectedNotes) {
+ // Create a raw lexer to pull all the comments out of the main file. We don't
+ // want to look in #include'd headers for expected-error strings.
+ FileID FID = PP.getSourceManager().getMainFileID();
+ if (PP.getSourceManager().getMainFileID().isInvalid())
+ return;
+
+ // Create a lexer to lex all the tokens of the main file in raw mode.
+ Lexer RawLex(FID, PP.getSourceManager(), PP.getLangOptions());
+
+ // Return comments as tokens, this is how we find expected diagnostics.
+ RawLex.SetCommentRetentionState(true);
+
+ Token Tok;
+ Tok.setKind(tok::comment);
+ while (Tok.isNot(tok::eof)) {
+ RawLex.Lex(Tok);
+ if (!Tok.is(tok::comment)) continue;
+
+ std::string Comment = PP.getSpelling(Tok);
+ if (Comment.empty()) continue;
+
+ // Find all expected errors.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP,
+ Tok.getLocation(), "expected-error");
+
+ // Find all expected warnings.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP,
+ Tok.getLocation(), "expected-warning");
+
+ // Find all expected notes.
+ FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP,
+ Tok.getLocation(), "expected-note");
+ };
+}
+
+/// PrintProblem - This takes a diagnostic map of the delta between expected and
+/// seen diagnostics. If there's anything in it, then something unexpected
+/// happened. Print the map out in a nice format and return "true". If the map
+/// is empty and we're not going to print things, then return "false".
+///
+static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr,
+ const_diag_iterator diag_begin,
+ const_diag_iterator diag_end,
+ const char *Kind, bool Expected) {
+ if (diag_begin == diag_end) return 0;
+
+ llvm::SmallString<256> Fmt;
+ llvm::raw_svector_ostream OS(Fmt);
+ for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
+ if (I->first.isInvalid() || !SourceMgr)
+ OS << "\n (frontend)";
+ else
+ OS << "\n Line " << SourceMgr->getInstantiationLineNumber(I->first);
+ OS << ": " << I->second;
+ }
+
+ Diags.Report(diag::err_verify_inconsistent_diags)
+ << Kind << !Expected << OS.str();
+ return std::distance(diag_begin, diag_end);
+}
+
+/// CompareDiagLists - Compare two diagnostic lists and return the difference
+/// between them.
+///
+static unsigned CompareDiagLists(Diagnostic &Diags,
+ SourceManager &SourceMgr,
+ const_diag_iterator d1_begin,
+ const_diag_iterator d1_end,
+ const_diag_iterator d2_begin,
+ const_diag_iterator d2_end,
+ const char *Label) {
+ DiagList LeftOnly;
+ DiagList Left(d1_begin, d1_end);
+ DiagList Right(d2_begin, d2_end);
+
+ for (const_diag_iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
+ unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(I->first);
+ const std::string &Diag1 = I->second;
+
+ DiagList::iterator II, IE;
+ for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
+ unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first);
+ if (LineNo1 != LineNo2) continue;
+
+ const std::string &Diag2 = II->second;
+ if (Diag2.find(Diag1) != std::string::npos ||
+ Diag1.find(Diag2) != std::string::npos) {
+ break;
+ }
+ }
+ if (II == IE) {
+ // Not found.
+ LeftOnly.push_back(*I);
+ } else {
+ // Found. The same cannot be found twice.
+ Right.erase(II);
+ }
+ }
+ // Now all that's left in Right are those that were not matched.
+
+ return (PrintProblem(Diags, &SourceMgr,
+ LeftOnly.begin(), LeftOnly.end(), Label, true) +
+ PrintProblem(Diags, &SourceMgr,
+ Right.begin(), Right.end(), Label, false));
+}
+
+/// CheckResults - This compares the expected results to those that
+/// were actually reported. It emits any discrepencies. Return "true" if there
+/// were problems. Return "false" otherwise.
+///
+static unsigned CheckResults(Diagnostic &Diags, SourceManager &SourceMgr,
+ const TextDiagnosticBuffer &Buffer,
+ const DiagList &ExpectedErrors,
+ const DiagList &ExpectedWarnings,
+ const DiagList &ExpectedNotes) {
+ // We want to capture the delta between what was expected and what was
+ // seen.
+ //
+ // Expected \ Seen - set expected but not seen
+ // Seen \ Expected - set seen but not expected
+ unsigned NumProblems = 0;
+
+ // See if there are error mismatches.
+ NumProblems += CompareDiagLists(Diags, SourceMgr,
+ ExpectedErrors.begin(), ExpectedErrors.end(),
+ Buffer.err_begin(), Buffer.err_end(),
+ "error");
+
+ // See if there are warning mismatches.
+ NumProblems += CompareDiagLists(Diags, SourceMgr,
+ ExpectedWarnings.begin(),
+ ExpectedWarnings.end(),
+ Buffer.warn_begin(), Buffer.warn_end(),
+ "warning");
+
+ // See if there are note mismatches.
+ NumProblems += CompareDiagLists(Diags, SourceMgr,
+ ExpectedNotes.begin(),
+ ExpectedNotes.end(),
+ Buffer.note_begin(), Buffer.note_end(),
+ "note");
+
+ return NumProblems;
+}
+
+
+void VerifyDiagnosticsClient::CheckDiagnostics() {
+ DiagList ExpectedErrors, ExpectedWarnings, ExpectedNotes;
+
+ // Ensure any diagnostics go to the primary client.
+ DiagnosticClient *CurClient = Diags.getClient();
+ Diags.setClient(PrimaryClient.get());
+
+ // If we have a preprocessor, scan the source for expected diagnostic
+ // markers. If not then any diagnostics are unexpected.
+ if (CurrentPreprocessor) {
+ FindExpectedDiags(*CurrentPreprocessor, ExpectedErrors, ExpectedWarnings,
+ ExpectedNotes);
+
+ // Check that the expected diagnostics occurred.
+ NumErrors += CheckResults(Diags, CurrentPreprocessor->getSourceManager(),
+ *Buffer,
+ ExpectedErrors, ExpectedWarnings, ExpectedNotes);
+ } else {
+ NumErrors += (PrintProblem(Diags, 0,
+ Buffer->err_begin(), Buffer->err_end(),
+ "error", false) +
+ PrintProblem(Diags, 0,
+ Buffer->warn_begin(), Buffer->warn_end(),
+ "warn", false) +
+ PrintProblem(Diags, 0,
+ Buffer->note_begin(), Buffer->note_end(),
+ "note", false));
+ }
+
+ Diags.setClient(CurClient);
+
+ // Reset the buffer, we have processed all the diagnostics in it.
+ Buffer.reset(new TextDiagnosticBuffer());
+}
diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp
index 7b01b0fb7416..ff44c9051663 100644
--- a/lib/Frontend/Warnings.cpp
+++ b/lib/Frontend/Warnings.cpp
@@ -24,6 +24,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Frontend/DiagnosticOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include <cstdio>
#include <cstring>
@@ -32,26 +33,24 @@
using namespace clang;
bool clang::ProcessWarningOptions(Diagnostic &Diags,
- std::vector<std::string> &Warnings,
- bool Pedantic, bool PedanticErrors,
- bool NoWarnings) {
+ const DiagnosticOptions &Opts) {
Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers
- Diags.setIgnoreAllWarnings(NoWarnings);
+ Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
// If -pedantic or -pedantic-errors was specified, then we want to map all
// extension diagnostics onto WARNING or ERROR unless the user has futz'd
// around with them explicitly.
- if (PedanticErrors)
+ if (Opts.PedanticErrors)
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Error);
- else if (Pedantic)
+ else if (Opts.Pedantic)
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Warn);
else
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Ignore);
// FIXME: -Wfatal-errors / -Wfatal-errors=foo
- for (unsigned i = 0, e = Warnings.size(); i != e; ++i) {
- const std::string &Opt = Warnings[i];
+ for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
+ const std::string &Opt = Opts.Warnings[i];
const char *OptStart = &Opt[0];
const char *OptEnd = OptStart+Opt.size();
assert(*OptEnd == 0 && "Expect null termination for lower-bound search");
@@ -100,8 +99,7 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags,
}
if (Diags.setDiagnosticGroupMapping(OptStart, Mapping))
- Diags.Report(FullSourceLoc(), diag::warn_unknown_warning_option)
- << ("-W" + Opt);
+ Diags.Report(diag::warn_unknown_warning_option) << ("-W" + Opt);
}
return false;