summaryrefslogtreecommitdiffstats
path: root/lib/Frontend
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTConsumers.cpp99
-rw-r--r--lib/Frontend/ASTUnit.cpp224
-rw-r--r--lib/Frontend/CMakeLists.txt45
-rw-r--r--lib/Frontend/CompilerInstance.cpp23
-rw-r--r--lib/Frontend/CompilerInvocation.cpp326
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp8
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp127
-rw-r--r--lib/Frontend/FrontendAction.cpp62
-rw-r--r--lib/Frontend/FrontendActions.cpp11
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp15
-rw-r--r--lib/Frontend/InitPreprocessor.cpp72
-rw-r--r--lib/Frontend/LayoutOverrideSource.cpp1
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp66
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp40
-rw-r--r--lib/Frontend/TextDiagnostic.cpp217
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp30
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp471
-rw-r--r--lib/Frontend/Warnings.cpp14
18 files changed, 1150 insertions, 701 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 390ae09..bb1a4e6 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -12,47 +12,116 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/ASTConsumers.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/FileManager.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecordLayout.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "llvm/Module.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Timer.h"
using namespace clang;
//===----------------------------------------------------------------------===//
/// ASTPrinter - Pretty-printer and dumper of ASTs
namespace {
- class ASTPrinter : public ASTConsumer {
+ class ASTPrinter : public ASTConsumer,
+ public RecursiveASTVisitor<ASTPrinter> {
+ typedef RecursiveASTVisitor<ASTPrinter> base;
+
+ public:
+ ASTPrinter(raw_ostream *Out = NULL, bool Dump = false,
+ StringRef FilterString = "")
+ : Out(Out ? *Out : llvm::outs()), Dump(Dump),
+ FilterString(FilterString) {}
+
+ virtual void HandleTranslationUnit(ASTContext &Context) {
+ TranslationUnitDecl *D = Context.getTranslationUnitDecl();
+
+ if (FilterString.empty()) {
+ if (Dump)
+ D->dump(Out);
+ else
+ D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
+ return;
+ }
+
+ TraverseDecl(D);
+ }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool TraverseDecl(Decl *D) {
+ if (filterMatches(D)) {
+ Out.changeColor(llvm::raw_ostream::BLUE) <<
+ (Dump ? "Dumping " : "Printing ") << getName(D) << ":\n";
+ Out.resetColor();
+ if (Dump)
+ D->dump(Out);
+ else
+ D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
+ // Don't traverse child nodes to avoid output duplication.
+ return true;
+ }
+ return base::TraverseDecl(D);
+ }
+
+ private:
+ std::string getName(Decl *D) {
+ if (isa<NamedDecl>(D))
+ return cast<NamedDecl>(D)->getQualifiedNameAsString();
+ return "";
+ }
+ bool filterMatches(Decl *D) {
+ return getName(D).find(FilterString) != std::string::npos;
+ }
+
raw_ostream &Out;
bool Dump;
+ std::string FilterString;
+ };
+
+ class ASTDeclNodeLister : public ASTConsumer,
+ public RecursiveASTVisitor<ASTDeclNodeLister> {
+ typedef RecursiveASTVisitor<ASTPrinter> base;
public:
- ASTPrinter(raw_ostream* o = NULL, bool Dump = false)
- : Out(o? *o : llvm::outs()), Dump(Dump) { }
+ ASTDeclNodeLister(raw_ostream *Out = NULL)
+ : Out(Out ? *Out : llvm::outs()) {}
virtual void HandleTranslationUnit(ASTContext &Context) {
- PrintingPolicy Policy = Context.getPrintingPolicy();
- Policy.Dump = Dump;
- Context.getTranslationUnitDecl()->print(Out, Policy, /*Indentation=*/0,
- /*PrintInstantiation=*/true);
+ TraverseDecl(Context.getTranslationUnitDecl());
}
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ virtual bool VisitNamedDecl(NamedDecl *D) {
+ Out << D->getQualifiedNameAsString() << "\n";
+ return true;
+ }
+
+ private:
+ raw_ostream &Out;
};
} // end anonymous namespace
-ASTConsumer *clang::CreateASTPrinter(raw_ostream* out) {
- return new ASTPrinter(out);
+ASTConsumer *clang::CreateASTPrinter(raw_ostream *Out,
+ StringRef FilterString) {
+ return new ASTPrinter(Out, /*Dump=*/ false, FilterString);
+}
+
+ASTConsumer *clang::CreateASTDumper(StringRef FilterString) {
+ return new ASTPrinter(0, /*Dump=*/ true, FilterString);
}
-ASTConsumer *clang::CreateASTDumper() {
- return new ASTPrinter(0, true);
+ASTConsumer *clang::CreateASTDeclNodeLister() {
+ return new ASTDeclNodeLister(0);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 7aa9603..42a6772 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -17,12 +17,6 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/Job.h"
-#include "clang/Driver/ArgList.h"
-#include "clang/Driver/Options.h"
-#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
@@ -122,7 +116,8 @@ static OnDiskDataMap &getOnDiskDataMap() {
}
static void cleanupOnDiskMapAtExit(void) {
- // No mutex required here since we are leaving the program.
+ // Use the mutex because there can be an alive thread destroying an ASTUnit.
+ llvm::MutexGuard Guard(getOnDiskMutex());
OnDiskDataMap &M = getOnDiskDataMap();
for (OnDiskDataMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
// We don't worry about freeing the memory associated with OnDiskDataMap.
@@ -220,6 +215,7 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
NumWarningsInPreamble(0),
ShouldCacheCodeCompletionResults(false),
+ IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
CompletionCacheTopLevelHashValue(0),
PreambleTopLevelHashValue(0),
CurrentTopLevelHashValue(0),
@@ -275,43 +271,43 @@ static unsigned getDeclShowContexts(NamedDecl *ND,
if (!ND)
return 0;
- unsigned Contexts = 0;
+ uint64_t Contexts = 0;
if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
// Types can appear in these contexts.
if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
- Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
- | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
- | (1 << (CodeCompletionContext::CCC_Statement - 1))
- | (1 << (CodeCompletionContext::CCC_Type - 1))
- | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
+ Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
+ | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
+ | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
+ | (1LL << CodeCompletionContext::CCC_Statement)
+ | (1LL << CodeCompletionContext::CCC_Type)
+ | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
// In C++, types can appear in expressions contexts (for functional casts).
if (LangOpts.CPlusPlus)
- Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
+ Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
// In Objective-C, message sends can send interfaces. In Objective-C++,
// all types are available due to functional casts.
if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
- Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+ Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
// In Objective-C, you can only be a subclass of another Objective-C class
if (isa<ObjCInterfaceDecl>(ND))
- Contexts |= (1 << (CodeCompletionContext::CCC_ObjCInterfaceName - 1));
+ Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
// Deal with tag names.
if (isa<EnumDecl>(ND)) {
- Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
+ Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);
// Part of the nested-name-specifier in C++0x.
if (LangOpts.CPlusPlus0x)
IsNestedNameSpecifier = true;
} else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
if (Record->isUnion())
- Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
+ Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);
else
- Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+ Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
if (LangOpts.CPlusPlus)
IsNestedNameSpecifier = true;
@@ -319,16 +315,16 @@ static unsigned getDeclShowContexts(NamedDecl *ND,
IsNestedNameSpecifier = true;
} else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
// Values can appear in these contexts.
- Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
- | (1 << (CodeCompletionContext::CCC_Expression - 1))
- | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+ Contexts = (1LL << CodeCompletionContext::CCC_Statement)
+ | (1LL << CodeCompletionContext::CCC_Expression)
+ | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
+ | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
} else if (isa<ObjCProtocolDecl>(ND)) {
- Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
+ Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName);
} else if (isa<ObjCCategoryDecl>(ND)) {
- Contexts = (1 << (CodeCompletionContext::CCC_ObjCCategoryName - 1));
+ Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);
} else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
- Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
+ Contexts = (1LL << CodeCompletionContext::CCC_Namespace);
// Part of the nested-name-specifier.
IsNestedNameSpecifier = true;
@@ -364,7 +360,8 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedCodeCompletionResult CachedResult;
CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
*CachedCompletionAllocator,
- getCodeCompletionTUInfo());
+ getCodeCompletionTUInfo(),
+ IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
Ctx->getLangOpts(),
IsNestedNameSpecifier);
@@ -402,23 +399,23 @@ void ASTUnit::CacheCodeCompletionResults() {
if (TheSema->Context.getLangOpts().CPlusPlus &&
IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
// The contexts in which a nested-name-specifier can appear in C++.
- unsigned NNSContexts
- = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
- | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
- | (1 << (CodeCompletionContext::CCC_Statement - 1))
- | (1 << (CodeCompletionContext::CCC_Expression - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
- | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
- | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
- | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
- | (1 << (CodeCompletionContext::CCC_Type - 1))
- | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1))
- | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
+ uint64_t NNSContexts
+ = (1LL << CodeCompletionContext::CCC_TopLevel)
+ | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
+ | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
+ | (1LL << CodeCompletionContext::CCC_Statement)
+ | (1LL << CodeCompletionContext::CCC_Expression)
+ | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
+ | (1LL << CodeCompletionContext::CCC_EnumTag)
+ | (1LL << CodeCompletionContext::CCC_UnionTag)
+ | (1LL << CodeCompletionContext::CCC_ClassOrStructTag)
+ | (1LL << CodeCompletionContext::CCC_Type)
+ | (1LL << CodeCompletionContext::CCC_PotentiallyQualifiedName)
+ | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
if (isa<NamespaceDecl>(Results[I].Declaration) ||
isa<NamespaceAliasDecl>(Results[I].Declaration))
- NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1));
+ NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
if (unsigned RemainingContexts
= NNSContexts & ~CachedResult.ShowInContexts) {
@@ -429,7 +426,8 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedResult.Completion
= Results[I].CreateCodeCompletionString(*TheSema,
*CachedCompletionAllocator,
- getCodeCompletionTUInfo());
+ getCodeCompletionTUInfo(),
+ IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts = RemainingContexts;
CachedResult.Priority = CCP_NestedNameSpecifier;
CachedResult.TypeClass = STC_Void;
@@ -451,20 +449,21 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedResult.Completion
= Results[I].CreateCodeCompletionString(*TheSema,
*CachedCompletionAllocator,
- getCodeCompletionTUInfo());
+ getCodeCompletionTUInfo(),
+ IncludeBriefCommentsInCodeCompletion);
CachedResult.ShowInContexts
- = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
- | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
- | (1 << (CodeCompletionContext::CCC_Statement - 1))
- | (1 << (CodeCompletionContext::CCC_Expression - 1))
- | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
- | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
- | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1))
- | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
- | (1 << (CodeCompletionContext::CCC_OtherWithMacros - 1));
+ = (1LL << CodeCompletionContext::CCC_TopLevel)
+ | (1LL << CodeCompletionContext::CCC_ObjCInterface)
+ | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
+ | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
+ | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
+ | (1LL << CodeCompletionContext::CCC_Statement)
+ | (1LL << CodeCompletionContext::CCC_Expression)
+ | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
+ | (1LL << CodeCompletionContext::CCC_MacroNameUse)
+ | (1LL << CodeCompletionContext::CCC_PreprocessorExpression)
+ | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
+ | (1LL << CodeCompletionContext::CCC_OtherWithMacros);
CachedResult.Priority = Results[I].Priority;
CachedResult.Kind = Results[I].CursorKind;
@@ -659,7 +658,8 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
RemappedFile *RemappedFiles,
unsigned NumRemappedFiles,
bool CaptureDiagnostics,
- bool AllowPCHWithCompilerErrors) {
+ bool AllowPCHWithCompilerErrors,
+ bool UserFilesAreVolatile) {
OwningPtr<ASTUnit> AST(new ASTUnit(true));
// Recover resources if we crash before exiting this method.
@@ -675,8 +675,10 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->Diagnostics = Diags;
AST->FileMgr = new FileManager(FileSystemOpts);
+ AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
- AST->getFileManager());
+ AST->getFileManager(),
+ UserFilesAreVolatile);
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager(),
AST->getDiagnostics(),
AST->ASTFileLangOpts,
@@ -1078,7 +1080,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
LangOpts = &Clang->getLangOpts();
FileSystemOpts = Clang->getFileSystemOpts();
FileMgr = new FileManager(FileSystemOpts);
- SourceMgr = new SourceManager(getDiagnostics(), *FileMgr);
+ SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
+ UserFilesAreVolatile);
TheSema.reset();
Ctx = 0;
PP = 0;
@@ -1139,7 +1142,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
StoredDiagnostics);
}
- Act->Execute();
+ if (!Act->Execute())
+ goto error;
transferASTDataFromCompilerInstance(*Clang);
@@ -1665,7 +1669,8 @@ StringRef ASTUnit::getMainFileName() const {
ASTUnit *ASTUnit::create(CompilerInvocation *CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- bool CaptureDiagnostics) {
+ bool CaptureDiagnostics,
+ bool UserFilesAreVolatile) {
OwningPtr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
@@ -1673,7 +1678,9 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI,
AST->Invocation = CI;
AST->FileSystemOpts = CI->getFileSystemOpts();
AST->FileMgr = new FileManager(AST->FileSystemOpts);
- AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr);
+ AST->UserFilesAreVolatile = UserFilesAreVolatile;
+ AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
+ UserFilesAreVolatile);
return AST.take();
}
@@ -1688,6 +1695,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
bool CaptureDiagnostics,
bool PrecompilePreamble,
bool CacheCodeCompletionResults,
+ bool IncludeBriefCommentsInCodeCompletion,
+ bool UserFilesAreVolatile,
OwningPtr<ASTUnit> *ErrAST) {
assert(CI && "A CompilerInvocation is required");
@@ -1695,7 +1704,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
ASTUnit *AST = Unit;
if (!AST) {
// Create the AST unit.
- OwnAST.reset(create(CI, Diags, CaptureDiagnostics));
+ OwnAST.reset(create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile));
AST = OwnAST.get();
}
@@ -1709,6 +1718,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
AST->PreambleRebuildCounter = 2;
AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
+ AST->IncludeBriefCommentsInCodeCompletion
+ = IncludeBriefCommentsInCodeCompletion;
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
@@ -1801,7 +1812,13 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
AST->getCurrentTopLevelHashValue()));
Clang->setASTConsumer(new MultiplexConsumer(Consumers));
}
- Act->Execute();
+ if (!Act->Execute()) {
+ AST->transferASTDataFromCompilerInstance(*Clang);
+ if (OwnAST && ErrAST)
+ ErrAST->swap(OwnAST);
+
+ return 0;
+ }
// Steal the created target, context, and preprocessor.
AST->transferASTDataFromCompilerInstance(*Clang);
@@ -1849,7 +1866,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
bool CaptureDiagnostics,
bool PrecompilePreamble,
TranslationUnitKind TUKind,
- bool CacheCodeCompletionResults) {
+ bool CacheCodeCompletionResults,
+ bool IncludeBriefCommentsInCodeCompletion,
+ bool UserFilesAreVolatile) {
// Create the AST unit.
OwningPtr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
@@ -1859,7 +1878,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
+ AST->IncludeBriefCommentsInCodeCompletion
+ = IncludeBriefCommentsInCodeCompletion;
AST->Invocation = CI;
+ AST->UserFilesAreVolatile = UserFilesAreVolatile;
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
@@ -1883,8 +1905,10 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
bool PrecompilePreamble,
TranslationUnitKind TUKind,
bool CacheCodeCompletionResults,
+ bool IncludeBriefCommentsInCodeCompletion,
bool AllowPCHWithCompilerErrors,
bool SkipFunctionBodies,
+ bool UserFilesAreVolatile,
OwningPtr<ASTUnit> *ErrAST) {
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
@@ -1942,6 +1966,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->TUKind = TUKind;
AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
+ AST->IncludeBriefCommentsInCodeCompletion
+ = IncludeBriefCommentsInCodeCompletion;
+ AST->UserFilesAreVolatile = UserFilesAreVolatile;
AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
AST->StoredDiagnostics.swap(StoredDiagnostics);
AST->Invocation = CI;
@@ -2034,38 +2061,37 @@ namespace {
/// results from an ASTUnit with the code-completion results provided to it,
/// then passes the result on to
class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
- unsigned long long NormalContexts;
+ uint64_t NormalContexts;
ASTUnit &AST;
CodeCompleteConsumer &Next;
public:
AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
- bool IncludeMacros, bool IncludeCodePatterns,
- bool IncludeGlobals)
- : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
- Next.isOutputBinary()), AST(AST), Next(Next)
+ const CodeCompleteOptions &CodeCompleteOpts)
+ : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()),
+ AST(AST), Next(Next)
{
// Compute the set of contexts in which we will look when we don't have
// any information about the specific context.
NormalContexts
- = (1LL << (CodeCompletionContext::CCC_TopLevel - 1))
- | (1LL << (CodeCompletionContext::CCC_ObjCInterface - 1))
- | (1LL << (CodeCompletionContext::CCC_ObjCImplementation - 1))
- | (1LL << (CodeCompletionContext::CCC_ObjCIvarList - 1))
- | (1LL << (CodeCompletionContext::CCC_Statement - 1))
- | (1LL << (CodeCompletionContext::CCC_Expression - 1))
- | (1LL << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
- | (1LL << (CodeCompletionContext::CCC_DotMemberAccess - 1))
- | (1LL << (CodeCompletionContext::CCC_ArrowMemberAccess - 1))
- | (1LL << (CodeCompletionContext::CCC_ObjCPropertyAccess - 1))
- | (1LL << (CodeCompletionContext::CCC_ObjCProtocolName - 1))
- | (1LL << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
- | (1LL << (CodeCompletionContext::CCC_Recovery - 1));
+ = (1LL << CodeCompletionContext::CCC_TopLevel)
+ | (1LL << CodeCompletionContext::CCC_ObjCInterface)
+ | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
+ | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
+ | (1LL << CodeCompletionContext::CCC_Statement)
+ | (1LL << CodeCompletionContext::CCC_Expression)
+ | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
+ | (1LL << CodeCompletionContext::CCC_DotMemberAccess)
+ | (1LL << CodeCompletionContext::CCC_ArrowMemberAccess)
+ | (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess)
+ | (1LL << CodeCompletionContext::CCC_ObjCProtocolName)
+ | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
+ | (1LL << CodeCompletionContext::CCC_Recovery);
if (AST.getASTContext().getLangOpts().CPlusPlus)
- NormalContexts |= (1LL << (CodeCompletionContext::CCC_EnumTag - 1))
- | (1LL << (CodeCompletionContext::CCC_UnionTag - 1))
- | (1LL << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+ NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag)
+ | (1LL << CodeCompletionContext::CCC_UnionTag)
+ | (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
}
virtual void ProcessCodeCompleteResults(Sema &S,
@@ -2180,9 +2206,9 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
unsigned NumResults) {
// Merge the results we were given with the results we cached.
bool AddedResult = false;
- unsigned InContexts
- = (Context.getKind() == CodeCompletionContext::CCC_Recovery? NormalContexts
- : (1ULL << (Context.getKind() - 1)));
+ uint64_t InContexts =
+ Context.getKind() == CodeCompletionContext::CCC_Recovery
+ ? NormalContexts : (1LL << Context.getKind());
// Contains the set of names that are hidden by "local" completion results.
llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
typedef CodeCompletionResult Result;
@@ -2273,6 +2299,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
unsigned NumRemappedFiles,
bool IncludeMacros,
bool IncludeCodePatterns,
+ bool IncludeBriefComments,
CodeCompleteConsumer &Consumer,
DiagnosticsEngine &Diag, LangOptions &LangOpts,
SourceManager &SourceMgr, FileManager &FileMgr,
@@ -2289,13 +2316,17 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
CCInvocation(new CompilerInvocation(*Invocation));
FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();
+ CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts;
PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();
- FrontendOpts.ShowMacrosInCodeCompletion
- = IncludeMacros && CachedCompletionResults.empty();
- FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
- FrontendOpts.ShowGlobalSymbolsInCodeCompletion
- = CachedCompletionResults.empty();
+ CodeCompleteOpts.IncludeMacros = IncludeMacros &&
+ CachedCompletionResults.empty();
+ CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;
+ CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();
+ CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;
+
+ assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);
+
FrontendOpts.CodeCompletionAt.FileName = File;
FrontendOpts.CodeCompletionAt.Line = Line;
FrontendOpts.CodeCompletionAt.Column = Column;
@@ -2364,10 +2395,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
// Use the code completion consumer we were given, but adding any cached
// code-completion results.
AugmentedCodeCompleteConsumer *AugmentedConsumer
- = new AugmentedCodeCompleteConsumer(*this, Consumer,
- FrontendOpts.ShowMacrosInCodeCompletion,
- FrontendOpts.ShowCodePatternsInCodeCompletion,
- FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
+ = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);
Clang->setCodeCompletionConsumer(AugmentedConsumer);
Clang->getFrontendOpts().SkipFunctionBodies = true;
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 2bee240..0566d54 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -1,14 +1,3 @@
-set( LLVM_USED_LIBS
- clangAST
- clangBasic
- clangDriver
- clangEdit
- clangLex
- clangParse
- clangSema
- clangSerialization
- )
-
add_clang_library(clangFrontend
ASTConsumers.cpp
ASTMerge.cpp
@@ -41,21 +30,29 @@ add_clang_library(clangFrontend
Warnings.cpp
)
-IF(MSVC)
- get_target_property(NON_ANSI_COMPILE_FLAGS clangFrontend COMPILE_FLAGS)
- string(REPLACE /Za
- "" NON_ANSI_COMPILE_FLAGS
- ${NON_ANSI_COMPILE_FLAGS})
- set_target_properties(clangFrontend PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
-ENDIF(MSVC)
-
-add_dependencies(clangFrontend
+add_dependencies(clangFrontend
ClangAttrClasses
ClangAttrList
- ClangCC1Options
- ClangDiagnosticFrontend
+ ClangAttrParsedAttrList
+ ClangCommentNodes
+ ClangDeclNodes
+ ClangDiagnosticAST
+ ClangDiagnosticCommon
+ ClangDiagnosticDriver
+ ClangDiagnosticFrontend
ClangDiagnosticLex
ClangDiagnosticSema
ClangDriverOptions
- ClangDeclNodes
- ClangStmtNodes)
+ ClangStmtNodes
+ )
+
+target_link_libraries(clangFrontend
+ clangAST
+ clangBasic
+ clangDriver
+ clangEdit
+ clangLex
+ clangParse
+ clangSema
+ clangSerialization
+ )
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 803e418..6de1531 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -387,9 +387,7 @@ void CompilerInstance::createCodeCompletionConsumer() {
setCodeCompletionConsumer(
createCodeCompletionConsumer(getPreprocessor(),
Loc.FileName, Loc.Line, Loc.Column,
- getFrontendOpts().ShowMacrosInCodeCompletion,
- getFrontendOpts().ShowCodePatternsInCodeCompletion,
- getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
+ getFrontendOpts().CodeCompleteOpts,
llvm::outs()));
if (!CompletionConsumer)
return;
@@ -415,16 +413,13 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
const std::string &Filename,
unsigned Line,
unsigned Column,
- bool ShowMacros,
- bool ShowCodePatterns,
- bool ShowGlobals,
+ const CodeCompleteOptions &Opts,
raw_ostream &OS) {
if (EnableCodeCompletion(PP, Filename, Line, Column))
return 0;
// Set up the creation routine for code-completion.
- return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
- ShowGlobals, OS);
+ return new PrintingCodeCompleteConsumer(Opts, OS);
}
void CompilerInstance::createSema(TranslationUnitKind TUKind,
@@ -456,7 +451,7 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) {
FileMgr->FixupRelativePath(NewOutFile);
if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename,
NewOutFile.str())) {
- getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
+ getDiagnostics().Report(diag::err_unable_to_rename_temp)
<< it->TempFilename << it->Filename << ec.message();
bool existed;
@@ -560,7 +555,8 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
TempPath += "-%%%%%%%%";
int fd;
if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
- /*makeAbsolute=*/false) == llvm::errc::success) {
+ /*makeAbsolute=*/false, 0664)
+ == llvm::errc::success) {
OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
OSFile = TempFile = TempPath.str();
}
@@ -859,13 +855,6 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
}
// Determine what file we're searching from.
- SourceManager &SourceMgr = getSourceManager();
- SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
- const FileEntry *CurFile
- = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc));
- if (!CurFile)
- CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
-
StringRef ModuleName = Path[0].first->getName();
SourceLocation ModuleNameLoc = Path[0].second;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 4c5b063..d39679c 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -13,7 +13,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
-#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/Options.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/OptTable.h"
#include "clang/Driver/Option.h"
@@ -181,8 +181,21 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, ToArgsList &Res) {
}
static void CodeGenOptsToArgs(const CodeGenOptions &Opts, ToArgsList &Res) {
- if (Opts.DebugInfo)
- Res.push_back("-g");
+ switch (Opts.DebugInfo) {
+ case CodeGenOptions::NoDebugInfo:
+ break;
+ case CodeGenOptions::DebugLineTablesOnly:
+ Res.push_back("-gline-tables-only");
+ break;
+ case CodeGenOptions::LimitedDebugInfo:
+ Res.push_back("-g");
+ Res.push_back("-flimit-debug-info");
+ break;
+ case CodeGenOptions::FullDebugInfo:
+ Res.push_back("-g");
+ Res.push_back("-fno-limit-debug-info");
+ break;
+ }
if (Opts.DisableLLVMOpts)
Res.push_back("-disable-llvm-optzns");
if (Opts.DisableRedZone)
@@ -193,14 +206,12 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, ToArgsList &Res) {
Res.push_back("-fdebug-compilation-dir", Opts.DebugCompilationDir);
if (!Opts.DwarfDebugFlags.empty())
Res.push_back("-dwarf-debug-flags", Opts.DwarfDebugFlags);
- if (Opts.ObjCRuntimeHasARC)
- Res.push_back("-fobjc-runtime-has-arc");
- if (Opts.ObjCRuntimeHasTerminate)
- Res.push_back("-fobjc-runtime-has-terminate");
if (Opts.EmitGcovArcs)
Res.push_back("-femit-coverage-data");
if (Opts.EmitGcovNotes)
Res.push_back("-femit-coverage-notes");
+ if (Opts.EmitOpenCLArgMetadata)
+ Res.push_back("-cl-kernel-arg-info");
if (!Opts.MergeAllConstants)
Res.push_back("-fno-merge-all-constants");
if (Opts.NoCommon)
@@ -270,6 +281,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, ToArgsList &Res) {
Res.push_back("-fobjc-dispatch-method=non-legacy");
break;
}
+ if (Opts.BoundsChecking > 0)
+ Res.push_back("-fbounds-checking=" + llvm::utostr(Opts.BoundsChecking));
if (Opts.NumRegisterParameters)
Res.push_back("-mregparm", llvm::utostr(Opts.NumRegisterParameters));
if (Opts.NoGlobalMerge)
@@ -296,6 +309,20 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, ToArgsList &Res) {
Res.push_back("-disable-llvm-verifier");
for (unsigned i = 0, e = Opts.BackendOptions.size(); i != e; ++i)
Res.push_back("-backend-option", Opts.BackendOptions[i]);
+
+ switch (Opts.DefaultTLSModel) {
+ case CodeGenOptions::GeneralDynamicTLSModel:
+ break;
+ case CodeGenOptions::LocalDynamicTLSModel:
+ Res.push_back("-ftls-model=local-dynamic");
+ break;
+ case CodeGenOptions::InitialExecTLSModel:
+ Res.push_back("-ftls-model=initial-exec");
+ break;
+ case CodeGenOptions::LocalExecTLSModel:
+ Res.push_back("-ftls-model=local-exec");
+ break;
+ }
}
static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
@@ -407,6 +434,7 @@ static const char *getActionName(frontend::ActionKind Kind) {
case frontend::PluginAction:
llvm_unreachable("Invalid kind!");
+ case frontend::ASTDeclList: return "-ast-list";
case frontend::ASTDump: return "-ast-dump";
case frontend::ASTDumpXML: return "-ast-dump-xml";
case frontend::ASTPrint: return "-ast-print";
@@ -445,6 +473,18 @@ static void FileSystemOptsToArgs(const FileSystemOptions &Opts, ToArgsList &Res)
Res.push_back("-working-directory", Opts.WorkingDir);
}
+static void CodeCompleteOptionsToArgs(const CodeCompleteOptions &Opts,
+ ToArgsList &Res) {
+ if (Opts.IncludeMacros)
+ Res.push_back("-code-completion-macros");
+ if (Opts.IncludeCodePatterns)
+ Res.push_back("-code-completion-patterns");
+ if (!Opts.IncludeGlobals)
+ Res.push_back("-no-code-completion-globals");
+ if (Opts.IncludeBriefComments)
+ Res.push_back("-code-completion-brief-comments");
+}
+
static void FrontendOptsToArgs(const FrontendOptions &Opts, ToArgsList &Res) {
if (Opts.DisableFree)
Res.push_back("-disable-free");
@@ -452,12 +492,6 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, ToArgsList &Res) {
Res.push_back("-relocatable-pch");
if (Opts.ShowHelp)
Res.push_back("-help");
- if (Opts.ShowMacrosInCodeCompletion)
- Res.push_back("-code-completion-macros");
- if (Opts.ShowCodePatternsInCodeCompletion)
- Res.push_back("-code-completion-patterns");
- if (!Opts.ShowGlobalSymbolsInCodeCompletion)
- Res.push_back("-no-code-completion-globals");
if (Opts.ShowStats)
Res.push_back("-print-stats");
if (Opts.ShowTimers)
@@ -485,6 +519,7 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, ToArgsList &Res) {
Res.push_back("-arcmt-migrate");
break;
}
+ CodeCompleteOptionsToArgs(Opts.CodeCompleteOpts, Res);
if (!Opts.MTMigrateDir.empty())
Res.push_back("-mt-migrate-directory", Opts.MTMigrateDir);
if (!Opts.ARCMTMigrateReportOut.empty())
@@ -524,6 +559,8 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, ToArgsList &Res) {
for(unsigned i = 0, e = Opts.PluginArgs.size(); i != e; ++i)
Res.push_back("-plugin-arg-" + Opts.ActionName, Opts.PluginArgs[i]);
}
+ if (!Opts.ASTDumpFilter.empty())
+ Res.push_back("-ast-dump-filter", Opts.ASTDumpFilter);
for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i)
Res.push_back("-load", Opts.Plugins[i]);
for (unsigned i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) {
@@ -608,6 +645,16 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
Res.push_back(E.Path);
}
+ /// User-specified system header prefixes.
+ for (unsigned i = 0, e = Opts.SystemHeaderPrefixes.size(); i != e; ++i) {
+ if (Opts.SystemHeaderPrefixes[i].IsSystemHeader)
+ Res.push_back("-isystem-prefix");
+ else
+ Res.push_back("-ino-system-prefix");
+
+ Res.push_back(Opts.SystemHeaderPrefixes[i].Prefix);
+ }
+
if (!Opts.ResourceDir.empty())
Res.push_back("-resource-dir", Opts.ResourceDir);
if (!Opts.ModuleCachePath.empty())
@@ -653,8 +700,6 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
Res.push_back("-fmsc-version=" + llvm::utostr(Opts.MSCVersion));
if (Opts.Borland)
Res.push_back("-fborland-extensions");
- if (!Opts.ObjCNonFragileABI)
- Res.push_back("-fobjc-fragile-abi");
if (Opts.ObjCDefaultSynthProperties)
Res.push_back("-fobjc-default-synthesize-properties");
// NoInline is implicit.
@@ -690,8 +735,6 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
Res.push_back("-fno-rtti");
if (Opts.MSBitfields)
Res.push_back("-mms-bitfields");
- if (!Opts.NeXTRuntime)
- Res.push_back("-fgnu-runtime");
if (Opts.Freestanding)
Res.push_back("-ffreestanding");
if (Opts.NoBuiltin)
@@ -721,6 +764,11 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
Res.push_back("-ftrapv-handler", Opts.OverflowHandler);
break;
}
+ switch (Opts.getFPContractMode()) {
+ case LangOptions::FPC_Off: Res.push_back("-ffp-contract=off"); break;
+ case LangOptions::FPC_On: Res.push_back("-ffp-contract=on"); break;
+ case LangOptions::FPC_Fast: Res.push_back("-ffp-contract=fast"); break;
+ }
if (Opts.HeinousExtensions)
Res.push_back("-fheinous-gnu-extensions");
// Optimize is implicit.
@@ -761,6 +809,7 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
Res.push_back("-fobjc-gc-only");
}
}
+ Res.push_back("-fobjc-runtime=" + Opts.ObjCRuntime.getAsString());
if (Opts.ObjCAutoRefCount)
Res.push_back("-fobjc-arc");
if (Opts.ObjCRuntimeHasWeak)
@@ -770,7 +819,7 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
if (Opts.AppleKext)
Res.push_back("-fapple-kext");
-
+
if (Opts.getVisibilityMode() != DefaultVisibility) {
Res.push_back("-fvisibility");
if (Opts.getVisibilityMode() == HiddenVisibility) {
@@ -880,7 +929,7 @@ static void TargetOptsToArgs(const TargetOptions &Opts,
Res.push_back("-target-feature", Opts.Features[i]);
}
-void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
+void CompilerInvocation::toArgs(std::vector<std::string> &Res) const {
ToArgsList List(Res);
AnalyzerOptsToArgs(getAnalyzerOpts(), List);
CodeGenOptsToArgs(getCodeGenOpts(), List);
@@ -900,7 +949,7 @@ void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
//===----------------------------------------------------------------------===//
using namespace clang::driver;
-using namespace clang::driver::cc1options;
+using namespace clang::driver::options;
//
@@ -909,14 +958,66 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
unsigned DefaultOpt = 0;
if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable))
DefaultOpt = 2;
- // -Os/-Oz implies -O2
- return (Args.hasArg(OPT_Os) || Args.hasArg (OPT_Oz)) ? 2 :
- Args.getLastArgIntValue(OPT_O, DefaultOpt, Diags);
+
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O0))
+ return 0;
+
+ assert (A->getOption().matches(options::OPT_O));
+
+ llvm::StringRef S(A->getValue(Args));
+ if (S == "s" || S == "z" || S.empty())
+ return 2;
+
+ return Args.getLastArgIntValue(OPT_O, DefaultOpt, Diags);
+ }
+
+ return DefaultOpt;
+}
+
+static unsigned getOptimizationLevelSize(ArgList &Args, InputKind IK,
+ DiagnosticsEngine &Diags) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O)) {
+ switch (A->getValue(Args)[0]) {
+ default:
+ return 0;
+ case 's':
+ return 1;
+ case 'z':
+ return 2;
+ }
+ }
+ }
+ return 0;
+}
+
+static void addWarningArgs(ArgList &Args, std::vector<std::string> &Warnings) {
+ for (arg_iterator I = Args.filtered_begin(OPT_W_Group),
+ E = Args.filtered_end(); I != E; ++I) {
+ Arg *A = *I;
+ // If the argument is a pure flag, add its name (minus the "-W" at the beginning)
+ // to the warning list. Else, add its value (for the OPT_W case).
+ if (A->getOption().getKind() == Option::FlagClass) {
+ Warnings.push_back(A->getOption().getName().substr(2));
+ } else {
+ for (unsigned Idx = 0, End = A->getNumValues();
+ Idx < End; ++Idx) {
+ StringRef V = A->getValue(Args, Idx);
+ // "-Wl," and such are not warning options.
+ // FIXME: Should be handled by putting these in separate flags.
+ if (V.startswith("l,") || V.startswith("a,") || V.startswith("p,"))
+ continue;
+
+ Warnings.push_back(V);
+ }
+ }
+ }
}
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
- using namespace cc1options;
+ using namespace options;
bool Success = true;
if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
StringRef Name = A->getValue(Args);
@@ -1026,7 +1127,6 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG);
Opts.CFGAddImplicitDtors = Args.hasArg(OPT_analysis_CFGAddImplicitDtors);
- Opts.CFGAddInitializers = Args.hasArg(OPT_analysis_CFGAddInitializers);
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags);
@@ -1066,7 +1166,7 @@ static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
- using namespace cc1options;
+ using namespace options;
bool Success = true;
unsigned OptLevel = getOptimizationLevel(Args, IK, Diags);
@@ -1083,12 +1183,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
: CodeGenOptions::OnlyAlwaysInlining;
// -fno-inline-functions overrides OptimizationLevel > 1.
Opts.NoInline = Args.hasArg(OPT_fno_inline);
- Opts.Inlining = Args.hasArg(OPT_fno_inline_functions) ?
+ Opts.Inlining = Args.hasArg(OPT_fno_inline_functions) ?
CodeGenOptions::OnlyAlwaysInlining : Opts.Inlining;
- Opts.DebugInfo = Args.hasArg(OPT_g);
- Opts.LimitDebugInfo = !Args.hasArg(OPT_fno_limit_debug_info)
- || Args.hasArg(OPT_flimit_debug_info);
+ if (Args.hasArg(OPT_gline_tables_only)) {
+ Opts.DebugInfo = CodeGenOptions::DebugLineTablesOnly;
+ } else if (Args.hasArg(OPT_g_Flag)) {
+ if (Args.hasFlag(OPT_flimit_debug_info, OPT_fno_limit_debug_info, true))
+ Opts.DebugInfo = CodeGenOptions::LimitedDebugInfo;
+ else
+ Opts.DebugInfo = CodeGenOptions::FullDebugInfo;
+ }
+
Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
@@ -1099,8 +1205,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
- Opts.OptimizeSize = Args.hasArg(OPT_Os);
- Opts.OptimizeSize = Args.hasArg(OPT_Oz) ? 2 : Opts.OptimizeSize;
+ Opts.OptimizeSize = getOptimizationLevelSize(Args, IK, Diags);
Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
Args.hasArg(OPT_ffreestanding));
Opts.UnrollLoops = Args.hasArg(OPT_funroll_loops) ||
@@ -1108,8 +1213,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
- Opts.ObjCRuntimeHasARC = Args.hasArg(OPT_fobjc_runtime_has_arc);
- Opts.ObjCRuntimeHasTerminate = Args.hasArg(OPT_fobjc_runtime_has_terminate);
Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);
Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
@@ -1145,6 +1248,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ);
+ Opts.BoundsChecking = Args.getLastArgIntValue(OPT_fbounds_checking_EQ, 0,
+ Diags);
+ Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array);
Opts.FunctionSections = Args.hasArg(OPT_ffunction_sections);
Opts.DataSections = Args.hasArg(OPT_fdata_sections);
@@ -1156,6 +1262,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
+ Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
+ Opts.EmitMicrosoftInlineAsm = Args.hasArg(OPT_fenable_experimental_ms_inline_asm);
Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
@@ -1180,12 +1288,28 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
+ if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
+ StringRef Name = A->getValue(Args);
+ unsigned Model = llvm::StringSwitch<unsigned>(Name)
+ .Case("global-dynamic", CodeGenOptions::GeneralDynamicTLSModel)
+ .Case("local-dynamic", CodeGenOptions::LocalDynamicTLSModel)
+ .Case("initial-exec", CodeGenOptions::InitialExecTLSModel)
+ .Case("local-exec", CodeGenOptions::LocalExecTLSModel)
+ .Default(~0U);
+ if (Model == ~0U) {
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+ Success = false;
+ } else {
+ Opts.DefaultTLSModel = static_cast<CodeGenOptions::TLSModel>(Model);
+ }
+ }
+
return Success;
}
static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
ArgList &Args) {
- using namespace cc1options;
+ using namespace options;
Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file);
Opts.Targets = Args.getAllArgValues(OPT_MT);
Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
@@ -1198,7 +1322,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticsEngine *Diags) {
- using namespace cc1options;
+ using namespace options;
bool Success = true;
Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
@@ -1273,6 +1397,8 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+ Opts.ElideType = !Args.hasArg(OPT_fno_elide_type);
+ Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree);
Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags);
Opts.MacroBacktraceLimit
= Args.getLastArgIntValue(OPT_fmacro_backtrace_limit,
@@ -1295,16 +1421,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
}
Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
-
- for (arg_iterator it = Args.filtered_begin(OPT_W),
- ie = Args.filtered_end(); it != ie; ++it) {
- StringRef V = (*it)->getValue(Args);
- // "-Wl," and such are not warnings options.
- if (V.startswith("l,") || V.startswith("a,") || V.startswith("p,"))
- continue;
-
- Opts.Warnings.push_back(V);
- }
+ addWarningArgs(Args, Opts.Warnings);
return Success;
}
@@ -1315,12 +1432,14 @@ static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
- using namespace cc1options;
+ using namespace options;
Opts.ProgramAction = frontend::ParseSyntaxOnly;
if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
switch (A->getOption().getID()) {
default:
llvm_unreachable("Invalid option in group!");
+ case OPT_ast_list:
+ Opts.ProgramAction = frontend::ASTDeclList; break;
case OPT_ast_dump:
Opts.ProgramAction = frontend::ASTDump; break;
case OPT_ast_dump_xml:
@@ -1418,11 +1537,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.Plugins = Args.getAllArgValues(OPT_load);
Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch);
Opts.ShowHelp = Args.hasArg(OPT_help);
- Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros);
- Opts.ShowCodePatternsInCodeCompletion
- = Args.hasArg(OPT_code_completion_patterns);
- Opts.ShowGlobalSymbolsInCodeCompletion
- = !Args.hasArg(OPT_no_code_completion_globals);
Opts.ShowStats = Args.hasArg(OPT_print_stats);
Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
Opts.ShowVersion = Args.hasArg(OPT_version);
@@ -1432,6 +1546,17 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings);
Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile);
Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp);
+ Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter);
+
+ Opts.CodeCompleteOpts.IncludeMacros
+ = Args.hasArg(OPT_code_completion_macros);
+ Opts.CodeCompleteOpts.IncludeCodePatterns
+ = Args.hasArg(OPT_code_completion_patterns);
+ Opts.CodeCompleteOpts.IncludeGlobals
+ = !Args.hasArg(OPT_no_code_completion_globals);
+ Opts.CodeCompleteOpts.IncludeBriefComments
+ = Args.hasArg(OPT_code_completion_brief_comments);
+
Opts.OverrideRecordLayoutsFile
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
@@ -1535,7 +1660,7 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
}
static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
- using namespace cc1options;
+ using namespace options;
Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
Opts.Verbose = Args.hasArg(OPT_v);
Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
@@ -1620,6 +1745,14 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.AddPath((*I)->getValue(Args), frontend::System,
false, false, /*IgnoreSysRoot=*/true, /*IsInternal=*/true,
(*I)->getOption().matches(OPT_internal_externc_isystem));
+
+ // Add the path prefixes which are implicitly treated as being system headers.
+ for (arg_iterator I = Args.filtered_begin(OPT_isystem_prefix,
+ OPT_ino_system_prefix),
+ E = Args.filtered_end();
+ I != E; ++I)
+ Opts.AddSystemHeaderPrefix((*I)->getValue(Args),
+ (*I)->getOption().matches(OPT_isystem_prefix));
}
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
@@ -1677,9 +1810,22 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.HexFloats = Std.hasHexFloats();
Opts.ImplicitInt = Std.hasImplicitInt();
- // OpenCL has some additional defaults.
+ // Set OpenCL Version.
if (LangStd == LangStandard::lang_opencl) {
Opts.OpenCL = 1;
+ Opts.OpenCLVersion = 100;
+ }
+ else if (LangStd == LangStandard::lang_opencl11) {
+ Opts.OpenCL = 1;
+ Opts.OpenCLVersion = 110;
+ }
+ else if (LangStd == LangStandard::lang_opencl12) {
+ Opts.OpenCL = 1;
+ Opts.OpenCLVersion = 120;
+ }
+
+ // OpenCL has some additional defaults.
+ if (Opts.OpenCL) {
Opts.AltiVec = 0;
Opts.CXXOperatorNames = 1;
Opts.LaxVectorConversions = 0;
@@ -1751,13 +1897,24 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
}
+ // -cl-std only applies for OpenCL language standards.
+ // Override the -std option in this case.
if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
- if (strcmp(A->getValue(Args), "CL1.1") != 0) {
+ LangStandard::Kind OpenCLLangStd
+ = llvm::StringSwitch<LangStandard::Kind>(A->getValue(Args))
+ .Case("CL", LangStandard::lang_opencl)
+ .Case("CL1.1", LangStandard::lang_opencl11)
+ .Case("CL1.2", LangStandard::lang_opencl12)
+ .Default(LangStandard::lang_unspecified);
+
+ if (OpenCLLangStd == LangStandard::lang_unspecified) {
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
+ << A->getAsString(Args) << A->getValue(Args);
}
+ else
+ LangStd = OpenCLLangStd;
}
-
+
CompilerInvocation::setLangDefaults(Opts, IK, LangStd);
// We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
@@ -1772,16 +1929,23 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.CXXOperatorNames = 0;
if (Opts.ObjC1) {
+ if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
+ StringRef value = arg->getValue(Args);
+ if (Opts.ObjCRuntime.tryParse(value))
+ Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
+ }
+
if (Args.hasArg(OPT_fobjc_gc_only))
Opts.setGC(LangOptions::GCOnly);
else if (Args.hasArg(OPT_fobjc_gc))
Opts.setGC(LangOptions::HybridGC);
else if (Args.hasArg(OPT_fobjc_arc)) {
Opts.ObjCAutoRefCount = 1;
- if (Args.hasArg(OPT_fobjc_fragile_abi))
+ if (!Opts.ObjCRuntime.isNonFragile())
Diags.Report(diag::err_arc_nonfragile_abi);
}
+ Opts.ObjCRuntimeHasWeak = Opts.ObjCRuntime.hasWeak();
if (Args.hasArg(OPT_fobjc_runtime_has_weak))
Opts.ObjCRuntimeHasWeak = 1;
@@ -1825,6 +1989,18 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Diags.Report(diag::err_drv_invalid_value)
<< Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
+ if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
+ StringRef Val = A->getValue(Args);
+ if (Val == "fast")
+ Opts.setFPContractMode(LangOptions::FPC_Fast);
+ else if (Val == "on")
+ Opts.setFPContractMode(LangOptions::FPC_On);
+ else if (Val == "off")
+ Opts.setFPContractMode(LangOptions::FPC_Off);
+ else
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+ }
+
if (Args.hasArg(OPT_fvisibility_inlines_hidden))
Opts.InlineVisibilityHidden = 1;
@@ -1876,25 +2052,21 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
Opts.MathErrno = Args.hasArg(OPT_fmath_errno);
- Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 1024,
+ Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 512,
Diags);
Opts.ConstexprCallDepth = Args.getLastArgIntValue(OPT_fconstexpr_depth, 512,
Diags);
Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
- Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy,
+ Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy_EQ,
0, Diags);
Opts.MSBitfields = Args.hasArg(OPT_mms_bitfields);
- Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
Opts.ObjCConstantStringClass =
Args.getLastArgValue(OPT_fconstant_string_class);
- Opts.ObjCNonFragileABI = !Args.hasArg(OPT_fobjc_fragile_abi);
- if (Opts.ObjCNonFragileABI)
- Opts.ObjCNonFragileABI2 = true;
Opts.ObjCDefaultSynthProperties =
Args.hasArg(OPT_fobjc_default_synthesize_properties);
Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
- Opts.PackStruct = Args.getLastArgIntValue(OPT_fpack_struct, 0, Diags);
+ Opts.PackStruct = Args.getLastArgIntValue(OPT_fpack_struct_EQ, 0, Diags);
Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags);
Opts.PIELevel = Args.getLastArgIntValue(OPT_pie_level, 0, Diags);
Opts.Static = Args.hasArg(OPT_static_define);
@@ -1924,9 +2096,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.Deprecated);
// FIXME: Eliminate this dependency.
- unsigned Opt = getOptimizationLevel(Args, IK, Diags);
+ unsigned Opt = getOptimizationLevel(Args, IK, Diags),
+ OptSize = getOptimizationLevelSize(Args, IK, Diags);
Opts.Optimize = Opt != 0;
- Opts.OptimizeSize = Args.hasArg(OPT_Os) || Args.hasArg(OPT_Oz);
+ Opts.OptimizeSize = OptSize != 0;
// This is the __NO_INLINE__ define, which just depends on things like the
// optimization level and -fno-inline, not actually whether the backend has
@@ -1934,6 +2107,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline);
Opts.FastMath = Args.hasArg(OPT_ffast_math);
+ Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only);
unsigned SSP = Args.getLastArgIntValue(OPT_stack_protector, 0, Diags);
switch (SSP) {
@@ -1950,7 +2124,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
FileManager &FileMgr,
DiagnosticsEngine &Diags) {
- using namespace cc1options;
+ using namespace options;
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
if (const Arg *A = Args.getLastArg(OPT_token_cache))
@@ -2052,16 +2226,17 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
ArgList &Args) {
- using namespace cc1options;
+ using namespace options;
Opts.ShowCPP = !Args.hasArg(OPT_dM);
Opts.ShowComments = Args.hasArg(OPT_C);
Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
Opts.ShowMacroComments = Args.hasArg(OPT_CC);
Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+ Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
}
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
- using namespace cc1options;
+ using namespace options;
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
@@ -2083,7 +2258,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
bool Success = true;
// Parse the arguments.
- OwningPtr<OptTable> Opts(createCC1OptTable());
+ OwningPtr<OptTable> Opts(createDriverOptTable());
unsigned MissingArgIndex, MissingArgCount;
OwningPtr<InputArgList> Args(
Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
@@ -2102,6 +2277,15 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Success = false;
}
+ // Issue errors on arguments that are not valid for CC1.
+ for (ArgList::iterator I = Args->begin(), E = Args->end();
+ I != E; ++I) {
+ if (!(*I)->getOption().isCC1Option()) {
+ Diags.Report(diag::err_drv_unknown_argument) << (*I)->getAsString(*Args);
+ Success = false;
+ }
+ }
+
Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success;
Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success;
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index b477ade..0aca86e 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -43,13 +43,17 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
Args.push_back("<clang>"); // FIXME: Remove dummy argument.
Args.insert(Args.end(), ArgList.begin(), ArgList.end());
- // FIXME: Find a cleaner way to force the driver into restricted modes. We
- // also want to force it to use clang.
+ // FIXME: Find a cleaner way to force the driver into restricted modes.
Args.push_back("-fsyntax-only");
// FIXME: We shouldn't have to pass in the path info.
driver::Driver TheDriver("clang", llvm::sys::getDefaultTargetTriple(),
"a.out", false, *Diags);
+ // Force driver to use clang.
+ // FIXME: This seems like a hack. Maybe the "Clang" tool subclass should be
+ // available for using it to get the arguments, thus avoiding the overkill
+ // of using the driver.
+ TheDriver.setForcedClangUse();
// Don't check that inputs exist, they may have been remapped.
TheDriver.setCheckInputsExist(false);
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index 6c3bb1d..f052f90 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -22,56 +22,6 @@
#include <algorithm>
using namespace clang;
-/// Look through spelling locations for a macro argument expansion, and
-/// if found skip to it so that we can trace the argument rather than the macros
-/// in which that argument is used. If no macro argument expansion is found,
-/// don't skip anything and return the starting location.
-static SourceLocation skipToMacroArgExpansion(const SourceManager &SM,
- SourceLocation StartLoc) {
- for (SourceLocation L = StartLoc; L.isMacroID();
- L = SM.getImmediateSpellingLoc(L)) {
- if (SM.isMacroArgExpansion(L))
- return L;
- }
-
- // Otherwise just return initial location, there's nothing to skip.
- return StartLoc;
-}
-
-/// Gets the location of the immediate macro caller, one level up the stack
-/// toward the initial macro typed into the source.
-static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM,
- SourceLocation Loc) {
- if (!Loc.isMacroID()) return Loc;
-
- // When we have the location of (part of) an expanded parameter, its spelling
- // location points to the argument as typed into the macro call, and
- // therefore is used to locate the macro caller.
- if (SM.isMacroArgExpansion(Loc))
- return SM.getImmediateSpellingLoc(Loc);
-
- // Otherwise, the caller of the macro is located where this macro is
- // expanded (while the spelling is part of the macro definition).
- return SM.getImmediateExpansionRange(Loc).first;
-}
-
-/// Gets the location of the immediate macro callee, one level down the stack
-/// toward the leaf macro.
-static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM,
- SourceLocation Loc) {
- if (!Loc.isMacroID()) return Loc;
-
- // When we have the location of (part of) an expanded parameter, its
- // expansion location points to the unexpanded paramater reference within
- // the macro definition (or callee).
- if (SM.isMacroArgExpansion(Loc))
- return SM.getImmediateExpansionRange(Loc).first;
-
- // Otherwise, the callee of the macro is located where this location was
- // spelled inside the macro definition.
- return SM.getImmediateSpellingLoc(Loc);
-}
-
/// \brief Retrieve the name of the immediate macro expansion.
///
/// This routine starts from a source location, and finds the name of the macro
@@ -109,24 +59,9 @@ static StringRef getImmediateMacroName(SourceLocation Loc,
return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
}
-/// Get the presumed location of a diagnostic message. This computes the
-/// presumed location for the top of any macro backtrace when present.
-static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM,
- SourceLocation Loc) {
- // This is a condensed form of the algorithm used by emitCaretDiagnostic to
- // walk to the top of the macro call stack.
- while (Loc.isMacroID()) {
- Loc = skipToMacroArgExpansion(SM, Loc);
- Loc = getImmediateMacroCallerLoc(SM, Loc);
- }
-
- return SM.getPresumedLoc(Loc);
-}
-
-DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM,
- const LangOptions &LangOpts,
+DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts)
-: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
+: LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
DiagnosticRenderer::~DiagnosticRenderer() {}
@@ -184,18 +119,23 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints,
+ const SourceManager *SM,
DiagOrStoredDiag D) {
+ assert(SM || Loc.isInvalid());
beginDiagnostic(D, Level);
- PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc);
+ PresumedLoc PLoc;
+ if (Loc.isValid()) {
+ PLoc = SM->getPresumedLocForDisplay(Loc);
- // First, if this diagnostic is not in the main file, print out the
- // "included from" lines.
- emitIncludeStack(PLoc.getIncludeLoc(), Level);
+ // First, if this diagnostic is not in the main file, print out the
+ // "included from" lines.
+ emitIncludeStack(PLoc.getIncludeLoc(), Level, *SM);
+ }
// Next, emit the actual diagnostic message.
- emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D);
+ emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
// Only recurse if we have a valid location.
if (Loc.isValid()) {
@@ -205,7 +145,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
llvm::SmallVector<FixItHint, 8> MergedFixits;
if (!FixItHints.empty()) {
- mergeFixits(FixItHints, SM, LangOpts, MergedFixits);
+ mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
FixItHints = MergedFixits;
}
@@ -216,7 +156,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
MutableRanges.push_back(I->RemoveRange);
unsigned MacroDepth = 0;
- emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints,
+ emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, *SM,
MacroDepth);
}
@@ -230,6 +170,8 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
Diag.getRanges(), Diag.getFixIts(),
+ Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
+ : 0,
&Diag);
}
@@ -245,7 +187,8 @@ void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
/// \param Loc The include location of the current file (not the diagnostic
/// location).
void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
- DiagnosticsEngine::Level Level) {
+ DiagnosticsEngine::Level Level,
+ const SourceManager &SM) {
// Skip redundant include stacks altogether.
if (LastIncludeLoc == Loc)
return;
@@ -254,12 +197,13 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
return;
- emitIncludeStackRecursively(Loc);
+ emitIncludeStackRecursively(Loc, SM);
}
/// \brief Helper to recursivly walk up the include stack and print each layer
/// on the way back down.
-void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
+void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
+ const SourceManager &SM) {
if (Loc.isInvalid())
return;
@@ -268,10 +212,10 @@ void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
return;
// Emit the other include frames first.
- emitIncludeStackRecursively(PLoc.getIncludeLoc());
+ emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
// Emit the inclusion text/note.
- emitIncludeLocation(Loc, PLoc);
+ emitIncludeLocation(Loc, PLoc, SM);
}
/// \brief Recursively emit notes for each macro expansion and caret
@@ -292,6 +236,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints,
+ const SourceManager &SM,
unsigned &MacroDepth,
unsigned OnMacroInst)
{
@@ -302,26 +247,26 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
if (Loc.isFileID()) {
assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!");
MacroDepth = OnMacroInst;
- emitCodeContext(Loc, Level, Ranges, Hints);
+ emitCodeContext(Loc, Level, Ranges, Hints, SM);
return;
}
// Otherwise recurse through each macro expansion layer.
// When processing macros, skip over the expansions leading up to
// a macro argument, and trace the argument's expansion stack instead.
- Loc = skipToMacroArgExpansion(SM, Loc);
+ Loc = SM.skipToMacroArgExpansion(Loc);
- SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc);
+ SourceLocation OneLevelUp = SM.getImmediateMacroCallerLoc(Loc);
// FIXME: Map ranges?
- emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth,
+ emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, SM, MacroDepth,
OnMacroInst + 1);
// Save the original location so we can find the spelling of the macro call.
SourceLocation MacroLoc = Loc;
// Map the location.
- Loc = getImmediateMacroCalleeLoc(SM, Loc);
+ Loc = SM.getImmediateMacroCalleeLoc(Loc);
unsigned MacroSkipStart = 0, MacroSkipEnd = 0;
if (MacroDepth > DiagOpts.MacroBacktraceLimit &&
@@ -341,9 +286,9 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
I != E; ++I) {
SourceLocation Start = I->getBegin(), End = I->getEnd();
if (Start.isMacroID())
- I->setBegin(getImmediateMacroCalleeLoc(SM, Start));
+ I->setBegin(SM.getImmediateMacroCalleeLoc(Start));
if (End.isMacroID())
- I->setEnd(getImmediateMacroCalleeLoc(SM, End));
+ I->setEnd(SM.getImmediateMacroCalleeLoc(End));
}
if (Suppressed) {
@@ -365,22 +310,22 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
<< getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
Message.str(),
- Ranges, ArrayRef<FixItHint>());
+ Ranges, ArrayRef<FixItHint>(), &SM);
}
DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc,
- PresumedLoc PLoc) {
+ PresumedLoc PLoc,
+ const SourceManager &SM) {
// Generate a note indicating the include location.
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
Message << "in file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":";
- emitNote(Loc, Message.str());
+ emitNote(Loc, Message.str(), &SM);
}
void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) {
- emitNote(SourceLocation(), Message);
+ emitNote(SourceLocation(), Message, 0);
}
-
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index da4bdfa..a4321e7 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -83,31 +83,31 @@ public:
}
};
- /// \brief Checks deserialized declarations and emits error if a name
- /// matches one given in command-line using -error-on-deserialized-decl.
- class DeserializedDeclsChecker : public DelegatingDeserializationListener {
- ASTContext &Ctx;
- std::set<std::string> NamesToCheck;
-
- public:
- DeserializedDeclsChecker(ASTContext &Ctx,
- const std::set<std::string> &NamesToCheck,
- ASTDeserializationListener *Previous)
- : DelegatingDeserializationListener(Previous),
- Ctx(Ctx), NamesToCheck(NamesToCheck) { }
-
- virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {
- unsigned DiagID
- = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,
- "%0 was deserialized");
- Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)
- << ND->getNameAsString();
- }
-
- DelegatingDeserializationListener::DeclRead(ID, D);
- }
+/// \brief Checks deserialized declarations and emits error if a name
+/// matches one given in command-line using -error-on-deserialized-decl.
+class DeserializedDeclsChecker : public DelegatingDeserializationListener {
+ ASTContext &Ctx;
+ std::set<std::string> NamesToCheck;
+
+public:
+ DeserializedDeclsChecker(ASTContext &Ctx,
+ const std::set<std::string> &NamesToCheck,
+ ASTDeserializationListener *Previous)
+ : DelegatingDeserializationListener(Previous),
+ Ctx(Ctx), NamesToCheck(NamesToCheck) { }
+
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D) {
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) {
+ unsigned DiagID
+ = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error,
+ "%0 was deserialized");
+ Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID)
+ << ND->getNameAsString();
+ }
+
+ DelegatingDeserializationListener::DeclRead(ID, D);
+ }
};
} // end anonymous namespace
@@ -162,6 +162,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
setCurrentInput(Input);
setCompilerInstance(&CI);
+ bool HasBegunSourceFile = false;
if (!BeginInvocation(CI))
goto failure;
@@ -214,6 +215,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Inform the diagnostic client we are processing a source file.
CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
+ HasBegunSourceFile = true;
// Initialize the action.
if (!BeginSourceFileAction(CI, Input.File))
@@ -228,6 +230,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Inform the diagnostic client we are processing a source file.
CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
&CI.getPreprocessor());
+ HasBegunSourceFile = true;
// Initialize the action.
if (!BeginSourceFileAction(CI, Input.File))
@@ -309,13 +312,14 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.setFileManager(0);
}
- CI.getDiagnosticClient().EndSourceFile();
+ if (HasBegunSourceFile)
+ CI.getDiagnosticClient().EndSourceFile();
setCurrentInput(FrontendInputFile());
setCompilerInstance(0);
return false;
}
-void FrontendAction::Execute() {
+bool FrontendAction::Execute() {
CompilerInstance &CI = getCompilerInstance();
// Initialize the main file entry. This needs to be delayed until after PCH
@@ -325,7 +329,7 @@ void FrontendAction::Execute() {
getCurrentInput().IsSystem
? SrcMgr::C_System
: SrcMgr::C_User))
- return;
+ return false;
}
if (CI.hasFrontendTimer()) {
@@ -333,6 +337,8 @@ void FrontendAction::Execute() {
ExecuteAction();
}
else ExecuteAction();
+
+ return true;
}
void FrontendAction::EndSourceFile() {
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 737ee4a..24960cf 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -47,13 +47,18 @@ void InitOnlyAction::ExecuteAction() {
ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
- return CreateASTPrinter(OS);
+ return CreateASTPrinter(OS, CI.getFrontendOpts().ASTDumpFilter);
return 0;
}
ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
- return CreateASTDumper();
+ return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter);
+}
+
+ASTConsumer *ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ return CreateASTDeclNodeLister();
}
ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI,
@@ -131,7 +136,7 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
///
/// \param Module The module we're collecting includes from.
///
-/// \param Includes Will be augmented with the set of #includes or #imports
+/// \param Includes Will be augmented with the set of \#includes or \#imports
/// needed to load all of the named headers.
static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
FileManager &FileMgr,
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 3f7e682..8178f7a 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -40,6 +40,7 @@ class InitHeaderSearch {
std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
typedef std::vector<std::pair<IncludeDirGroup,
DirectoryLookup> >::const_iterator path_iterator;
+ std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
HeaderSearch &Headers;
bool Verbose;
std::string IncludeSysroot;
@@ -57,6 +58,12 @@ public:
bool isCXXAware, bool isUserSupplied,
bool isFramework, bool IgnoreSysRoot = false);
+ /// AddSystemHeaderPrefix - Add the specified prefix to the system header
+ /// prefix list.
+ void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
+ SystemHeaderPrefixes.push_back(std::make_pair(Prefix, IsSystemHeader));
+ }
+
/// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu
/// libstdc++.
void AddGnuCPlusPlusIncludePaths(StringRef Base,
@@ -210,6 +217,8 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
switch (os) {
case llvm::Triple::FreeBSD:
case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
+ case llvm::Triple::Bitrig:
break;
default:
// FIXME: temporary hack: hard-coded paths.
@@ -623,6 +632,8 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
bool DontSearchCurDir = false; // TODO: set to true if -I- is set?
Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir);
+ Headers.SetSystemHeaderPrefixes(SystemHeaderPrefixes);
+
// If verbose, print the list of directories that will be searched.
if (Verbose) {
llvm::errs() << "#include \"...\" search starts here:\n";
@@ -660,6 +671,10 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
Init.AddDefaultIncludePaths(Lang, Triple, HSOpts);
+ for (unsigned i = 0, e = HSOpts.SystemHeaderPrefixes.size(); i != e; ++i)
+ Init.AddSystemHeaderPrefix(HSOpts.SystemHeaderPrefixes[i].Prefix,
+ HSOpts.SystemHeaderPrefixes[i].IsSystemHeader);
+
if (HSOpts.UseBuiltinIncludes) {
// Set up the builtin include directory in the module map.
llvm::sys::Path P(HSOpts.ResourceDir);
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 93d49b0..1440da6 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -49,7 +49,7 @@ static void DefineBuiltinMacro(MacroBuilder &Builder, StringRef Macro,
}
}
-/// AddImplicitInclude - Add an implicit #include of the specified file to the
+/// AddImplicitInclude - Add an implicit \#include of the specified file to the
/// predefines buffer.
static void AddImplicitInclude(MacroBuilder &Builder, StringRef File,
FileManager &FileMgr) {
@@ -66,8 +66,8 @@ static void AddImplicitIncludeMacros(MacroBuilder &Builder,
Builder.append("##"); // ##?
}
-/// AddImplicitIncludePTH - Add an implicit #include using the original file
-/// used to generate a PTH cache.
+/// AddImplicitIncludePTH - Add an implicit \#include using the original file
+/// used to generate a PTH cache.
static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
StringRef ImplicitIncludePTH) {
PTHManager *P = PP.getPTHManager();
@@ -288,20 +288,16 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
else if (!LangOpts.GNUMode && LangOpts.Digraphs)
Builder.defineMacro("__STDC_VERSION__", "199409L");
} else {
- if (LangOpts.GNUMode)
- Builder.defineMacro("__cplusplus");
- else {
- // C++0x [cpp.predefined]p1:
- // The name_ _cplusplus is defined to the value 201103L when compiling a
- // C++ translation unit.
- if (LangOpts.CPlusPlus0x)
- Builder.defineMacro("__cplusplus", "201103L");
- // C++03 [cpp.predefined]p1:
- // The name_ _cplusplus is defined to the value 199711L when compiling a
- // C++ translation unit.
- else
- Builder.defineMacro("__cplusplus", "199711L");
- }
+ // C++11 [cpp.predefined]p1:
+ // The name __cplusplus is defined to the value 201103L when compiling a
+ // C++ translation unit.
+ if (LangOpts.CPlusPlus0x)
+ Builder.defineMacro("__cplusplus", "201103L");
+ // C++03 [cpp.predefined]p1:
+ // The name __cplusplus is defined to the value 199711L when compiling a
+ // C++ translation unit.
+ else
+ Builder.defineMacro("__cplusplus", "199711L");
}
if (LangOpts.ObjC1)
@@ -369,7 +365,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__GXX_EXPERIMENTAL_CXX0X__");
if (LangOpts.ObjC1) {
- if (LangOpts.ObjCNonFragileABI) {
+ if (LangOpts.ObjCRuntime.isNonFragile()) {
Builder.defineMacro("__OBJC2__");
if (LangOpts.ObjCExceptions)
@@ -379,8 +375,13 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (LangOpts.getGC() != LangOptions::NonGC)
Builder.defineMacro("__OBJC_GC__");
- if (LangOpts.NeXTRuntime)
+ if (LangOpts.ObjCRuntime.isNeXTFamily())
Builder.defineMacro("__NEXT_RUNTIME__");
+
+ Builder.defineMacro("IBOutlet", "__attribute__((iboutlet))");
+ Builder.defineMacro("IBOutletCollection(ClassName)",
+ "__attribute__((iboutletcollection(ClassName)))");
+ Builder.defineMacro("IBAction", "void)__attribute__((ibaction)");
}
// darwin_constant_cfstrings controls this. This is also dependent
@@ -444,6 +445,26 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// Initialize target-specific preprocessor defines.
+ // __BYTE_ORDER__ was added in GCC 4.6. It's analogous
+ // to the macro __BYTE_ORDER (no trailing underscores)
+ // from glibc's <endian.h> header.
+ // We don't support the PDP-11 as a target, but include
+ // the define so it can still be compared against.
+ Builder.defineMacro("__ORDER_LITTLE_ENDIAN__", "1234");
+ Builder.defineMacro("__ORDER_BIG_ENDIAN__", "4321");
+ Builder.defineMacro("__ORDER_PDP_ENDIAN__", "3412");
+ if (TI.isBigEndian())
+ Builder.defineMacro("__BYTE_ORDER__", "__ORDER_BIG_ENDIAN__");
+ else
+ Builder.defineMacro("__BYTE_ORDER__", "__ORDER_LITTLE_ENDIAN__");
+
+
+ if (TI.getPointerWidth(0) == 64 && TI.getLongWidth() == 64
+ && TI.getIntWidth() == 32) {
+ Builder.defineMacro("_LP64");
+ Builder.defineMacro("__LP64__");
+ }
+
// Define type sizing macros based on the target properties.
assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
Builder.defineMacro("__CHAR_BIT__", "8");
@@ -501,6 +522,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (!LangOpts.CharIsSigned)
Builder.defineMacro("__CHAR_UNSIGNED__");
+ if (!TargetInfo::isTypeSigned(TI.getWCharType()))
+ Builder.defineMacro("__WCHAR_UNSIGNED__");
+
if (!TargetInfo::isTypeSigned(TI.getWIntType()))
Builder.defineMacro("__WINT_UNSIGNED__");
@@ -520,15 +544,13 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (TI.getLongLongWidth() > TI.getLongWidth())
DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder);
- // Add __builtin_va_list typedef.
- Builder.append(TI.getVAListDeclaration());
-
if (const char *Prefix = TI.getUserLabelPrefix())
Builder.defineMacro("__USER_LABEL_PREFIX__", Prefix);
- // Build configuration options. FIXME: these should be controlled by
- // command line options or something.
- Builder.defineMacro("__FINITE_MATH_ONLY__", "0");
+ if (LangOpts.FastMath || LangOpts.FiniteMathOnly)
+ Builder.defineMacro("__FINITE_MATH_ONLY__", "1");
+ else
+ Builder.defineMacro("__FINITE_MATH_ONLY__", "0");
if (LangOpts.GNUInline)
Builder.defineMacro("__GNUC_GNU_INLINE__");
diff --git a/lib/Frontend/LayoutOverrideSource.cpp b/lib/Frontend/LayoutOverrideSource.cpp
index eb7865e..e023250 100644
--- a/lib/Frontend/LayoutOverrideSource.cpp
+++ b/lib/Frontend/LayoutOverrideSource.cpp
@@ -9,6 +9,7 @@
#include "clang/Frontend/LayoutOverrideSource.h"
#include "clang/AST/Decl.h"
#include "llvm/Support/raw_ostream.h"
+#include <cctype>
#include <fstream>
#include <string>
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 9e1587c..5311ed5 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -26,6 +26,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
+#include <cctype>
#include <cstdio>
using namespace clang;
@@ -87,7 +88,7 @@ private:
unsigned CurLine;
bool EmittedTokensOnThisLine;
- bool EmittedMacroOnThisLine;
+ bool EmittedDirectiveOnThisLine;
SrcMgr::CharacteristicKind FileType;
SmallString<512> CurFilename;
bool Initialized;
@@ -103,7 +104,7 @@ public:
CurLine = 0;
CurFilename += "<uninit>";
EmittedTokensOnThisLine = false;
- EmittedMacroOnThisLine = false;
+ EmittedDirectiveOnThisLine = false;
FileType = SrcMgr::C_User;
Initialized = false;
@@ -111,10 +112,15 @@ public:
UseLineDirective = PP.getLangOpts().MicrosoftExt;
}
- void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
+ void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
- bool StartNewLineIfNeeded();
+ void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; }
+ bool hasEmittedDirectiveOnThisLine() const {
+ return EmittedDirectiveOnThisLine;
+ }
+
+ bool startNewLineIfNeeded(bool ShouldUpdateCurrentLine = true);
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
@@ -158,11 +164,7 @@ public:
void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
const char *Extra,
unsigned ExtraLen) {
- if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
- OS << '\n';
- EmittedTokensOnThisLine = false;
- EmittedMacroOnThisLine = false;
- }
+ startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
// Emit #line directives or GNU line markers depending on what mode we're in.
if (UseLineDirective) {
@@ -207,23 +209,21 @@ bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) {
} else {
// Okay, we're in -P mode, which turns off line markers. However, we still
// need to emit a newline between tokens on different lines.
- if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
- OS << '\n';
- EmittedTokensOnThisLine = false;
- EmittedMacroOnThisLine = false;
- }
+ startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
}
CurLine = LineNo;
return true;
}
-bool PrintPPOutputPPCallbacks::StartNewLineIfNeeded() {
- if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
+bool
+PrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) {
+ if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) {
OS << '\n';
EmittedTokensOnThisLine = false;
- EmittedMacroOnThisLine = false;
- ++CurLine;
+ EmittedDirectiveOnThisLine = false;
+ if (ShouldUpdateCurrentLine)
+ ++CurLine;
return true;
}
@@ -307,7 +307,7 @@ void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
MoveToLine(MI->getDefinitionLoc());
PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS);
- EmittedMacroOnThisLine = true;
+ setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
@@ -317,12 +317,13 @@ void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
MoveToLine(MacroNameTok.getLocation());
OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName();
- EmittedMacroOnThisLine = true;
+ setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
const IdentifierInfo *Kind,
const std::string &Str) {
+ startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma comment(" << Kind->getName();
@@ -343,11 +344,12 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
}
OS << ')';
- EmittedTokensOnThisLine = true;
+ setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
StringRef Str) {
+ startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma message(";
@@ -366,26 +368,29 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc,
OS << '"';
OS << ')';
- EmittedTokensOnThisLine = true;
+ setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::
PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) {
+ startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma " << Namespace << " diagnostic push";
- EmittedTokensOnThisLine = true;
+ setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::
PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) {
+ startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma " << Namespace << " diagnostic pop";
- EmittedTokensOnThisLine = true;
+ setEmittedDirectiveOnThisLine();
}
void PrintPPOutputPPCallbacks::
PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
diag::Mapping Map, StringRef Str) {
+ startNewLineIfNeeded();
MoveToLine(Loc);
OS << "#pragma " << Namespace << " diagnostic ";
switch (Map) {
@@ -403,7 +408,7 @@ PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
break;
}
OS << " \"" << Str << '"';
- EmittedTokensOnThisLine = true;
+ setEmittedDirectiveOnThisLine();
}
/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
@@ -471,10 +476,9 @@ struct UnknownPragmaHandler : public PragmaHandler {
Token &PragmaTok) {
// Figure out what line we went to and insert the appropriate number of
// newline characters.
- Callbacks->StartNewLineIfNeeded();
+ Callbacks->startNewLineIfNeeded();
Callbacks->MoveToLine(PragmaTok.getLocation());
Callbacks->OS.write(Prefix, strlen(Prefix));
- Callbacks->SetEmittedTokensOnThisLine();
// Read and print all of the pragma tokens.
while (PragmaTok.isNot(tok::eod)) {
if (PragmaTok.hasLeadingSpace())
@@ -483,7 +487,7 @@ struct UnknownPragmaHandler : public PragmaHandler {
Callbacks->OS.write(&TokSpell[0], TokSpell.size());
PP.LexUnexpandedToken(PragmaTok);
}
- Callbacks->StartNewLineIfNeeded();
+ Callbacks->setEmittedDirectiveOnThisLine();
}
};
} // end anonymous namespace
@@ -497,6 +501,10 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
PrevPrevTok.startToken();
PrevTok.startToken();
while (1) {
+ if (Callbacks->hasEmittedDirectiveOnThisLine()) {
+ Callbacks->startNewLineIfNeeded();
+ Callbacks->MoveToLine(Tok.getLocation());
+ }
// If this token is at the start of a line, emit newlines if needed.
if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) {
@@ -533,7 +541,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
if (Tok.getKind() == tok::comment)
Callbacks->HandleNewlinesInToken(&S[0], S.size());
}
- Callbacks->SetEmittedTokensOnThisLine();
+ Callbacks->setEmittedTokensOnThisLine();
if (Tok.is(tok::eof)) break;
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 7bf8742..a20f30d 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -53,10 +53,9 @@ class SDiagsRenderer : public DiagnosticNoteRenderer {
RecordData &Record;
public:
SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record,
- const SourceManager &SM,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts)
- : DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
+ : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Writer(Writer), Record(Record){}
virtual ~SDiagsRenderer() {}
@@ -67,18 +66,21 @@ protected:
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
+ const SourceManager *SM,
DiagOrStoredDiag D);
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges) {}
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) {}
- void emitNote(SourceLocation Loc, StringRef Message);
+ void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM);
virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints);
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM);
virtual void beginDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level);
@@ -137,15 +139,16 @@ private:
unsigned getEmitFile(const char *Filename);
/// \brief Add SourceLocation information the specified record.
- void AddLocToRecord(SourceLocation Loc, const SourceManager &SM,
+ void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
PresumedLoc PLoc, RecordDataImpl &Record,
unsigned TokSize = 0);
/// \brief Add SourceLocation information the specified record.
void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
- const SourceManager &SM,
+ const SourceManager *SM,
unsigned TokSize = 0) {
- AddLocToRecord(Loc, SM, SM.getPresumedLoc(Loc), Record, TokSize);
+ AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
+ Record, TokSize);
}
/// \brief Add CharSourceRange information the specified record.
@@ -241,7 +244,7 @@ static void EmitRecordID(unsigned ID, const char *Name,
}
void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
- const SourceManager &SM,
+ const SourceManager *SM,
PresumedLoc PLoc,
RecordDataImpl &Record,
unsigned TokSize) {
@@ -257,19 +260,19 @@ void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
Record.push_back(getEmitFile(PLoc.getFilename()));
Record.push_back(PLoc.getLine());
Record.push_back(PLoc.getColumn()+TokSize);
- Record.push_back(SM.getFileOffset(Loc));
+ Record.push_back(SM->getFileOffset(Loc));
}
void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
RecordDataImpl &Record,
const SourceManager &SM) {
- AddLocToRecord(Range.getBegin(), Record, SM);
+ AddLocToRecord(Range.getBegin(), Record, &SM);
unsigned TokSize = 0;
if (Range.isTokenRange())
TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
SM, *LangOpts);
- AddLocToRecord(Range.getEnd(), Record, SM, TokSize);
+ AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
}
unsigned SDiagsWriter::getEmitFile(const char *FileName){
@@ -484,13 +487,15 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
diagBuf.clear();
Info.FormatDiagnostic(diagBuf);
- SourceManager &SM = Info.getSourceManager();
- SDiagsRenderer Renderer(*this, Record, SM, *LangOpts, DiagOpts);
+ const SourceManager *
+ SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0;
+ SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts);
Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
diagBuf.str(),
Info.getRanges(),
llvm::makeArrayRef(Info.getFixItHints(),
Info.getNumFixItHints()),
+ SM,
&Info);
}
@@ -500,6 +505,7 @@ SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<clang::CharSourceRange> Ranges,
+ const SourceManager *SM,
DiagOrStoredDiag D) {
// Emit the RECORD_DIAG record.
Writer.Record.clear();
@@ -539,7 +545,8 @@ void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange> &Ranges,
- ArrayRef<FixItHint> Hints) {
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {
// Emit Source Ranges.
for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end();
it != ei; ++it) {
@@ -562,7 +569,8 @@ void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
}
}
-void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message) {
+void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
+ const SourceManager *SM) {
Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
RecordData Record;
Record.push_back(RECORD_DIAG);
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 65fb1ae..9bb3e1d 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
+#include <cctype>
using namespace clang;
@@ -31,16 +32,36 @@ static const enum raw_ostream::Colors caretColor =
raw_ostream::GREEN;
static const enum raw_ostream::Colors warningColor =
raw_ostream::MAGENTA;
+static const enum raw_ostream::Colors templateColor =
+ raw_ostream::CYAN;
static const enum raw_ostream::Colors errorColor = raw_ostream::RED;
static const enum raw_ostream::Colors fatalColor = raw_ostream::RED;
// Used for changing only the bold attribute.
static const enum raw_ostream::Colors savedColor =
raw_ostream::SAVEDCOLOR;
+/// \brief Add highlights to differences in template strings.
+static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,
+ bool &Normal, bool Bold) {
+ for (unsigned i = 0, e = Str.size(); i < e; ++i)
+ if (Str[i] != ToggleHighlight) {
+ OS << Str[i];
+ } else {
+ if (Normal)
+ OS.changeColor(templateColor, true);
+ else {
+ OS.resetColor();
+ if (Bold)
+ OS.changeColor(savedColor, true);
+ }
+ Normal = !Normal;
+ }
+}
+
/// \brief Number of spaces to indent when word-wrapping.
const unsigned WordWrapIndentation = 6;
-int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
+static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
int bytes = 0;
while (0<i) {
if (SourceLine[--i]=='\t')
@@ -69,7 +90,7 @@ int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
/// \param TabStop used to expand tabs
/// \return pair(printable text, 'true' iff original text was printable)
///
-std::pair<SmallString<16>,bool>
+static std::pair<SmallString<16>, bool>
printableTextForNextCharacter(StringRef SourceLine, size_t *i,
unsigned TabStop) {
assert(i && "i must not be null");
@@ -146,7 +167,7 @@ printableTextForNextCharacter(StringRef SourceLine, size_t *i,
return std::make_pair(expandedByte, false);
}
-void expandTabs(std::string &SourceLine, unsigned TabStop) {
+static void expandTabs(std::string &SourceLine, unsigned TabStop) {
size_t i = SourceLine.size();
while (i>0) {
i--;
@@ -164,7 +185,7 @@ void expandTabs(std::string &SourceLine, unsigned TabStop) {
/// characters will appear at (numbering the first column as 0).
///
/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
-/// character) then the the array will map that byte to the first column the
+/// character) then the array will map that byte to the first column the
/// tab appears at and the next value in the map will have been incremented
/// more than once.
///
@@ -179,9 +200,9 @@ void expandTabs(std::string &SourceLine, unsigned TabStop) {
///
/// "a \t \u3042" -> {0,1,2,8,9,-1,-1,11}
///
-/// (\u3042 is represented in UTF-8 by three bytes and takes two columns to
+/// (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
/// display)
-void byteToColumn(StringRef SourceLine, unsigned TabStop,
+static void byteToColumn(StringRef SourceLine, unsigned TabStop,
SmallVectorImpl<int> &out) {
out.clear();
@@ -213,9 +234,9 @@ void byteToColumn(StringRef SourceLine, unsigned TabStop,
///
/// "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
///
-/// (\u3042 is represented in UTF-8 by three bytes and takes two columns to
+/// (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
/// display)
-void columnToByte(StringRef SourceLine, unsigned TabStop,
+static void columnToByte(StringRef SourceLine, unsigned TabStop,
SmallVectorImpl<int> &out) {
out.clear();
@@ -307,11 +328,11 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
// correctly.
unsigned CaretStart = 0, CaretEnd = CaretLine.size();
for (; CaretStart != CaretEnd; ++CaretStart)
- if (!isspace(CaretLine[CaretStart]))
+ if (!isspace(static_cast<unsigned char>(CaretLine[CaretStart])))
break;
for (; CaretEnd != CaretStart; --CaretEnd)
- if (!isspace(CaretLine[CaretEnd - 1]))
+ if (!isspace(static_cast<unsigned char>(CaretLine[CaretEnd - 1])))
break;
// caret has already been inserted into CaretLine so the above whitespace
@@ -322,17 +343,33 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
if (!FixItInsertionLine.empty()) {
unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
for (; FixItStart != FixItEnd; ++FixItStart)
- if (!isspace(FixItInsertionLine[FixItStart]))
+ if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItStart])))
break;
for (; FixItEnd != FixItStart; --FixItEnd)
- if (!isspace(FixItInsertionLine[FixItEnd - 1]))
+ if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItEnd - 1])))
break;
CaretStart = std::min(FixItStart, CaretStart);
CaretEnd = std::max(FixItEnd, CaretEnd);
}
+ // CaretEnd may have been set at the middle of a character
+ // If it's not at a character's first column then advance it past the current
+ // character.
+ while (static_cast<int>(CaretEnd) < map.columns() &&
+ -1 == map.columnToByte(CaretEnd))
+ ++CaretEnd;
+
+ assert((static_cast<int>(CaretStart) > map.columns() ||
+ -1!=map.columnToByte(CaretStart)) &&
+ "CaretStart must not point to a column in the middle of a source"
+ " line character");
+ assert((static_cast<int>(CaretEnd) > map.columns() ||
+ -1!=map.columnToByte(CaretEnd)) &&
+ "CaretEnd must not point to a column in the middle of a source line"
+ " character");
+
// CaretLine[CaretStart, CaretEnd) contains all of the interesting
// parts of the caret line. While this slice is smaller than the
// number of columns we have, try to grow the slice to encompass
@@ -366,12 +403,14 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
while (NewStart &&
- (map.byteToColumn(NewStart)==-1 || isspace(SourceLine[NewStart])))
+ (map.byteToColumn(NewStart)==-1 ||
+ isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
--NewStart;
// Skip over this bit of "interesting" text.
while (NewStart &&
- (map.byteToColumn(NewStart)!=-1 && !isspace(SourceLine[NewStart])))
+ (map.byteToColumn(NewStart)!=-1 &&
+ !isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
--NewStart;
// Move up to the non-whitespace character we just saw.
@@ -392,12 +431,14 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
// Skip over any whitespace we see here; we're looking for
// another bit of interesting text.
while (NewEnd<SourceLine.size() &&
- (map.byteToColumn(NewEnd)==-1 || isspace(SourceLine[NewEnd])))
+ (map.byteToColumn(NewEnd)==-1 ||
+ isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
++NewEnd;
// Skip over this bit of "interesting" text.
while (NewEnd<SourceLine.size() &&
- (map.byteToColumn(NewEnd)!=-1 && !isspace(SourceLine[NewEnd])))
+ (map.byteToColumn(NewEnd)!=-1 &&
+ !isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
++NewEnd;
unsigned NewColumns = map.byteToColumn(NewEnd) -
@@ -549,6 +590,7 @@ static unsigned findEndOfWord(unsigned Start, StringRef Str,
/// \param Column the column number at which the first character of \p
/// Str will be printed. This will be non-zero when part of the first
/// line has already been printed.
+/// \param Bold if the current text should be bold
/// \param Indentation the number of spaces to indent any lines beyond
/// the first line.
/// \returns true if word-wrapping was required, or false if the
@@ -556,8 +598,10 @@ static unsigned findEndOfWord(unsigned Start, StringRef Str,
static bool printWordWrapped(raw_ostream &OS, StringRef Str,
unsigned Columns,
unsigned Column = 0,
+ bool Bold = false,
unsigned Indentation = WordWrapIndentation) {
const unsigned Length = std::min(Str.find('\n'), Str.size());
+ bool TextNormal = true;
// The string used to indent each line.
SmallString<16> IndentStr;
@@ -581,7 +625,8 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str,
OS << ' ';
Column += 1;
}
- OS << Str.substr(WordStart, WordLength);
+ applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
+ TextNormal, Bold);
Column += WordLength;
continue;
}
@@ -590,22 +635,24 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str,
// line.
OS << '\n';
OS.write(&IndentStr[0], Indentation);
- OS << Str.substr(WordStart, WordLength);
+ applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
+ TextNormal, Bold);
Column = Indentation + WordLength;
Wrapped = true;
}
// Append any remaning text from the message with its existing formatting.
- OS << Str.substr(Length);
+ applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold);
+
+ assert(TextNormal && "Text highlighted at end of diagnostic message.");
return Wrapped;
}
TextDiagnostic::TextDiagnostic(raw_ostream &OS,
- const SourceManager &SM,
const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts)
- : DiagnosticRenderer(SM, LangOpts, DiagOpts), OS(OS) {}
+ : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
TextDiagnostic::~TextDiagnostic() {}
@@ -615,11 +662,13 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<clang::CharSourceRange> Ranges,
+ const SourceManager *SM,
DiagOrStoredDiag D) {
uint64_t StartOfLocationInfo = OS.tell();
// Emit the location of this particular diagnostic.
- emitDiagnosticLoc(Loc, PLoc, Level, Ranges);
+ if (Loc.isValid())
+ emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
if (DiagOpts.ShowColors)
OS.resetColor();
@@ -665,20 +714,27 @@ TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
StringRef Message,
unsigned CurrentColumn, unsigned Columns,
bool ShowColors) {
+ bool Bold = false;
if (ShowColors) {
// Print warnings, errors and fatal errors in bold, no color
switch (Level) {
- case DiagnosticsEngine::Warning: OS.changeColor(savedColor, true); break;
- case DiagnosticsEngine::Error: OS.changeColor(savedColor, true); break;
- case DiagnosticsEngine::Fatal: OS.changeColor(savedColor, true); break;
+ case DiagnosticsEngine::Warning:
+ case DiagnosticsEngine::Error:
+ case DiagnosticsEngine::Fatal:
+ OS.changeColor(savedColor, true);
+ Bold = true;
+ break;
default: break; //don't bold notes
}
}
if (Columns)
- printWordWrapped(OS, Message, Columns, CurrentColumn);
- else
- OS << Message;
+ printWordWrapped(OS, Message, Columns, CurrentColumn, Bold);
+ else {
+ bool Normal = true;
+ applyTemplateHighlighting(OS, Message, Normal, Bold);
+ assert(Normal && "Formatting should have returned to normal");
+ }
if (ShowColors)
OS.resetColor();
@@ -693,7 +749,8 @@ TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
/// ranges necessary.
void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges) {
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) {
if (PLoc.isInvalid()) {
// At least print the file name if available:
FileID FID = SM.getFileID(Loc);
@@ -799,7 +856,8 @@ void TextDiagnostic::emitBasicNote(StringRef Message) {
}
void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
- PresumedLoc PLoc) {
+ PresumedLoc PLoc,
+ const SourceManager &SM) {
if (DiagOpts.ShowLocation)
OS << "In file included from " << PLoc.getFilename() << ':'
<< PLoc.getLine() << ":\n";
@@ -817,7 +875,8 @@ void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
void TextDiagnostic::emitSnippetAndCaret(
SourceLocation Loc, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints) {
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {
assert(!Loc.isInvalid() && "must have a valid source location here");
assert(Loc.isFileID() && "must have a file location here");
@@ -840,17 +899,12 @@ void TextDiagnostic::emitSnippetAndCaret(
// Get information about the buffer it points into.
bool Invalid = false;
- StringRef BufData = SM.getBufferData(FID, &Invalid);
+ const char *BufStart = SM.getBufferData(FID, &Invalid).data();
if (Invalid)
return;
- const char *BufStart = BufData.data();
- const char *BufEnd = BufStart + BufData.size();
-
unsigned LineNo = SM.getLineNumber(FID, FileOffset);
unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
- unsigned CaretEndColNo
- = ColNo + Lexer::MeasureTokenLength(Loc, SM, LangOpts);
// Rewind from the current position to the start of the line.
const char *TokPtr = BufStart+FileOffset;
@@ -860,14 +914,9 @@ void TextDiagnostic::emitSnippetAndCaret(
// Compute the line end. Scan forward from the error position to the end of
// the line.
const char *LineEnd = TokPtr;
- while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd!=BufEnd)
+ while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
++LineEnd;
- // FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
- // the source line length as currently being computed. See
- // test/Misc/message-length.c.
- CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart));
-
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(LineStart, LineEnd);
@@ -881,7 +930,7 @@ void TextDiagnostic::emitSnippetAndCaret(
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
I != E; ++I)
- highlightRange(*I, LineNo, FID, sourceColMap, CaretLine);
+ highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
// Next, insert the caret itself.
ColNo = sourceColMap.byteToColumn(ColNo-1);
@@ -891,7 +940,7 @@ void TextDiagnostic::emitSnippetAndCaret(
std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
sourceColMap,
- Hints);
+ Hints, SM);
// If the source line is too long for our terminal, select only the
// "interesting" source region within that line.
@@ -934,11 +983,10 @@ void TextDiagnostic::emitSnippetAndCaret(
}
// Print out any parseable fixit information requested by the options.
- emitParseableFixits(Hints);
+ emitParseableFixits(Hints, SM);
}
-void TextDiagnostic::emitSnippet(StringRef line)
-{
+void TextDiagnostic::emitSnippet(StringRef line) {
if (line.empty())
return;
@@ -952,8 +1000,7 @@ void TextDiagnostic::emitSnippet(StringRef line)
= printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
bool was_printable = res.second;
- if (DiagOpts.ShowColors
- && was_printable==print_reversed) {
+ if (DiagOpts.ShowColors && was_printable == print_reversed) {
if (print_reversed)
OS.reverseColor();
OS << to_print;
@@ -979,7 +1026,8 @@ void TextDiagnostic::emitSnippet(StringRef line)
void TextDiagnostic::highlightRange(const CharSourceRange &R,
unsigned LineNo, FileID FID,
const SourceColumnMap &map,
- std::string &CaretLine) {
+ std::string &CaretLine,
+ const SourceManager &SM) {
if (!R.isValid()) return;
SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
@@ -1064,49 +1112,63 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
std::string TextDiagnostic::buildFixItInsertionLine(
unsigned LineNo,
const SourceColumnMap &map,
- ArrayRef<FixItHint> Hints) {
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {
std::string FixItInsertionLine;
if (Hints.empty() || !DiagOpts.ShowFixits)
return FixItInsertionLine;
+ unsigned PrevHintEndCol = 0;
for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
I != E; ++I) {
if (!I->CodeToInsert.empty()) {
// We have an insertion hint. Determine whether the inserted
- // code is on the same line as the caret.
+ // code contains no newlines and is on the same line as the caret.
std::pair<FileID, unsigned> HintLocInfo
= SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin());
- if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second)) {
+ if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
+ StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) {
// Insert the new code into the line just below the code
// that the user wrote.
- unsigned HintColNo
+ // Note: When modifying this function, be very careful about what is a
+ // "column" (printed width, platform-dependent) and what is a
+ // "byte offset" (SourceManager "column").
+ unsigned HintByteOffset
= SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
- // hint must start inside the source or right at the end
- assert(HintColNo<static_cast<unsigned>(map.bytes())+1);
- HintColNo = map.byteToColumn(HintColNo);
-
- // FIXME: if the fixit includes tabs or other characters that do not
- // take up a single column per byte when displayed then
- // I->CodeToInsert.size() is not a column number and we're mixing
- // units (columns + bytes). We should get printable versions
- // of each fixit before using them.
- unsigned LastColumnModified
- = HintColNo + I->CodeToInsert.size();
-
- if (LastColumnModified > static_cast<unsigned>(map.bytes())) {
- unsigned LastExistingColumn = map.byteToColumn(map.bytes());
- unsigned AddedColumns = LastColumnModified-LastExistingColumn;
- LastColumnModified = LastExistingColumn + AddedColumns;
- } else {
- LastColumnModified = map.byteToColumn(LastColumnModified);
- }
+ // The hint must start inside the source or right at the end
+ assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
+ unsigned HintCol = map.byteToColumn(HintByteOffset);
+
+ // If we inserted a long previous hint, push this one forwards, and add
+ // an extra space to show that this is not part of the previous
+ // completion. This is sort of the best we can do when two hints appear
+ // to overlap.
+ //
+ // Note that if this hint is located immediately after the previous
+ // hint, no space will be added, since the location is more important.
+ if (HintCol < PrevHintEndCol)
+ HintCol = PrevHintEndCol + 1;
+
+ // FIXME: This function handles multibyte characters in the source, but
+ // not in the fixits. This assertion is intended to catch unintended
+ // use of multibyte characters in fixits. If we decide to do this, we'll
+ // have to track separate byte widths for the source and fixit lines.
+ assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) ==
+ I->CodeToInsert.size());
+
+ // This relies on one byte per column in our fixit hints.
+ // This should NOT use HintByteOffset, because the source might have
+ // Unicode characters in earlier columns.
+ unsigned LastColumnModified = HintCol + I->CodeToInsert.size();
if (LastColumnModified > FixItInsertionLine.size())
FixItInsertionLine.resize(LastColumnModified, ' ');
- assert(HintColNo+I->CodeToInsert.size() <= FixItInsertionLine.size());
+
std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
- FixItInsertionLine.begin() + HintColNo);
+ FixItInsertionLine.begin() + HintCol);
+
+ PrevHintEndCol = LastColumnModified;
} else {
FixItInsertionLine.clear();
break;
@@ -1119,7 +1181,8 @@ std::string TextDiagnostic::buildFixItInsertionLine(
return FixItInsertionLine;
}
-void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) {
+void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {
if (!DiagOpts.ShowParseableFixits)
return;
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 6445a0c..382e156 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -27,7 +27,7 @@ using namespace clang;
TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os,
const DiagnosticOptions &diags,
bool _OwnsOutputStream)
- : OS(os), LangOpts(0), DiagOpts(&diags), SM(0),
+ : OS(os), DiagOpts(&diags),
OwnsOutputStream(_OwnsOutputStream) {
}
@@ -38,11 +38,11 @@ TextDiagnosticPrinter::~TextDiagnosticPrinter() {
void TextDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
const Preprocessor *PP) {
- LangOpts = &LO;
+ // Build the TextDiagnostic utility.
+ TextDiag.reset(new TextDiagnostic(OS, LO, *DiagOpts));
}
void TextDiagnosticPrinter::EndSourceFile() {
- LangOpts = 0;
TextDiag.reset(0);
}
@@ -79,16 +79,6 @@ static void printDiagnosticOptions(raw_ostream &OS,
Started = true;
}
- // If the diagnostic is an extension diagnostic and not enabled by default
- // then it must have been turned on with -pedantic.
- bool EnabledByDefault;
- if (DiagnosticIDs::isBuiltinExtensionDiag(Info.getID(),
- EnabledByDefault) &&
- !EnabledByDefault) {
- OS << (Started ? "," : " [") << "-pedantic";
- Started = true;
- }
-
StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID());
if (!Opt.empty()) {
OS << (Started ? "," : " [") << "-W" << Opt;
@@ -128,7 +118,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
llvm::raw_svector_ostream DiagMessageStream(OutStr);
printDiagnosticOptions(DiagMessageStream, Level, Info, *DiagOpts);
- // Keeps track of the the starting position of the location
+ // Keeps track of the starting position of the location
// information (e.g., "foo.c:10:4:") that precedes the error
// message. We use this information to determine how long the
// file+line+column number prefix is.
@@ -152,22 +142,16 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
}
// Assert that the rest of our infrastructure is setup properly.
- assert(LangOpts && "Unexpected diagnostic outside source file processing");
assert(DiagOpts && "Unexpected diagnostic without options set");
assert(Info.hasSourceManager() &&
"Unexpected diagnostic with no source manager");
-
- // Rebuild the TextDiagnostic utility if missing or the source manager has
- // changed.
- if (!TextDiag || SM != &Info.getSourceManager()) {
- SM = &Info.getSourceManager();
- TextDiag.reset(new TextDiagnostic(OS, *SM, *LangOpts, *DiagOpts));
- }
+ assert(TextDiag && "Unexpected diagnostic outside source file processing");
TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(),
Info.getRanges(),
llvm::makeArrayRef(Info.getFixItHints(),
- Info.getNumFixItHints()));
+ Info.getNumFixItHints()),
+ &Info.getSourceManager());
OS.flush();
}
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 552282d..a9378a1 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -11,58 +11,108 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/FileManager.h"
#include "clang/Frontend/VerifyDiagnosticConsumer.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
-#include <climits>
+#include <cctype>
using namespace clang;
+typedef VerifyDiagnosticConsumer::Directive Directive;
+typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList;
+typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData;
VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
- : Diags(_Diags), PrimaryClient(Diags.getClient()),
- OwnsPrimaryClient(Diags.ownsClient()),
- Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0)
+ : Diags(_Diags),
+ PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()),
+ Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0),
+ ActiveSourceFiles(0)
{
Diags.takeClient();
}
VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
+ assert(!ActiveSourceFiles && "Incomplete parsing of source files!");
+ assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
CheckDiagnostics();
Diags.takeClient();
if (OwnsPrimaryClient)
delete PrimaryClient;
}
+#ifndef NDEBUG
+namespace {
+class VerifyFileTracker : public PPCallbacks {
+ typedef VerifyDiagnosticConsumer::FilesParsedForDirectivesSet ListType;
+ ListType &FilesList;
+ SourceManager &SM;
+
+public:
+ VerifyFileTracker(ListType &FilesList, SourceManager &SM)
+ : FilesList(FilesList), SM(SM) { }
+
+ /// \brief Hook into the preprocessor and update the list of parsed
+ /// files when the preprocessor indicates a new file is entered.
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) {
+ if (const FileEntry *E = SM.getFileEntryForID(SM.getFileID(Loc)))
+ FilesList.insert(E);
+ }
+};
+} // End anonymous namespace.
+#endif
+
// DiagnosticConsumer interface.
void VerifyDiagnosticConsumer::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);
+ // Attach comment handler on first invocation.
+ if (++ActiveSourceFiles == 1) {
+ if (PP) {
+ CurrentPreprocessor = PP;
+ const_cast<Preprocessor*>(PP)->addCommentHandler(this);
+#ifndef NDEBUG
+ VerifyFileTracker *V = new VerifyFileTracker(FilesParsedForDirectives,
+ PP->getSourceManager());
+ const_cast<Preprocessor*>(PP)->addPPCallbacks(V);
+#endif
+ }
+ }
+ assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!");
PrimaryClient->BeginSourceFile(LangOpts, PP);
}
void VerifyDiagnosticConsumer::EndSourceFile() {
- CheckDiagnostics();
-
+ assert(ActiveSourceFiles && "No active source files!");
PrimaryClient->EndSourceFile();
- CurrentPreprocessor = 0;
+ // Detach comment handler once last active source file completed.
+ if (--ActiveSourceFiles == 0) {
+ if (CurrentPreprocessor)
+ const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this);
+
+ // Check diagnostics once last file completed.
+ CheckDiagnostics();
+ CurrentPreprocessor = 0;
+ }
}
void VerifyDiagnosticConsumer::HandleDiagnostic(
DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
- if (FirstErrorFID.isInvalid() && Info.hasSourceManager()) {
- const SourceManager &SM = Info.getSourceManager();
- FirstErrorFID = SM.getFileID(Info.getLocation());
+#ifndef NDEBUG
+ if (Info.hasSourceManager()) {
+ FileID FID = Info.getSourceManager().getFileID(Info.getLocation());
+ if (!FID.isInvalid())
+ FilesWithDiagnostics.insert(FID);
}
+#endif
// 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);
@@ -77,54 +127,21 @@ typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
namespace {
-/// Directive - Abstract class representing a parsed verify directive.
-///
-class Directive {
-public:
- static Directive* Create(bool RegexKind, const SourceLocation &Location,
- const std::string &Text, unsigned Count);
-public:
- /// Constant representing one or more matches aka regex "+".
- static const unsigned OneOrMoreCount = UINT_MAX;
-
- SourceLocation Location;
- const std::string Text;
- unsigned Count;
-
- virtual ~Directive() { }
-
- // Returns true if directive text is valid.
- // Otherwise returns false and populates E.
- virtual bool isValid(std::string &Error) = 0;
-
- // Returns true on match.
- virtual bool Match(const std::string &S) = 0;
-
-protected:
- Directive(const SourceLocation &Location, const std::string &Text,
- unsigned Count)
- : Location(Location), Text(Text), Count(Count) { }
-
-private:
- Directive(const Directive&); // DO NOT IMPLEMENT
- void operator=(const Directive&); // DO NOT IMPLEMENT
-};
-
/// StandardDirective - Directive with string matching.
///
class StandardDirective : public Directive {
public:
- StandardDirective(const SourceLocation &Location, const std::string &Text,
- unsigned Count)
- : Directive(Location, Text, Count) { }
+ StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
+ StringRef Text, unsigned Min, unsigned Max)
+ : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max) { }
virtual bool isValid(std::string &Error) {
// all strings are considered valid; even empty ones
return true;
}
- virtual bool Match(const std::string &S) {
- return S.find(Text) != std::string::npos;
+ virtual bool match(StringRef S) {
+ return S.find(Text) != StringRef::npos;
}
};
@@ -132,9 +149,9 @@ public:
///
class RegexDirective : public Directive {
public:
- RegexDirective(const SourceLocation &Location, const std::string &Text,
- unsigned Count)
- : Directive(Location, Text, Count), Regex(Text) { }
+ RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
+ StringRef Text, unsigned Min, unsigned Max)
+ : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max), Regex(Text) { }
virtual bool isValid(std::string &Error) {
if (Regex.isValid(Error))
@@ -142,7 +159,7 @@ public:
return false;
}
- virtual bool Match(const std::string &S) {
+ virtual bool match(StringRef S) {
return Regex.match(S);
}
@@ -150,30 +167,11 @@ private:
llvm::Regex Regex;
};
-typedef std::vector<Directive*> DirectiveList;
-
-/// ExpectedData - owns directive objects and deletes on destructor.
-///
-struct ExpectedData {
- DirectiveList Errors;
- DirectiveList Warnings;
- DirectiveList Notes;
-
- ~ExpectedData() {
- DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 };
- for (DirectiveList **PL = Lists; *PL; ++PL) {
- DirectiveList * const L = *PL;
- for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I)
- delete *I;
- }
- }
-};
-
class ParseHelper
{
public:
- ParseHelper(const char *Begin, const char *End)
- : Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { }
+ ParseHelper(StringRef S)
+ : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(NULL) { }
// Return true if string literal is next.
bool Next(StringRef S) {
@@ -240,78 +238,134 @@ private:
/// ParseDirective - Go through the comment and see if it indicates expected
/// diagnostics. If so, then put them in the appropriate directive list.
///
-static void ParseDirective(const char *CommentStart, unsigned CommentLen,
- ExpectedData &ED, Preprocessor &PP,
- SourceLocation Pos) {
+/// Returns true if any valid directives were found.
+static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
+ SourceLocation Pos, DiagnosticsEngine &Diags) {
// A single comment may contain multiple directives.
- for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) {
- // search for token: expected
+ bool FoundDirective = false;
+ for (ParseHelper PH(S); !PH.Done();) {
+ // Search for token: expected
if (!PH.Search("expected"))
break;
PH.Advance();
- // next token: -
+ // Next token: -
if (!PH.Next("-"))
continue;
PH.Advance();
- // next token: { error | warning | note }
+ // Next token: { error | warning | note }
DirectiveList* DL = NULL;
if (PH.Next("error"))
- DL = &ED.Errors;
+ DL = ED ? &ED->Errors : NULL;
else if (PH.Next("warning"))
- DL = &ED.Warnings;
+ DL = ED ? &ED->Warnings : NULL;
else if (PH.Next("note"))
- DL = &ED.Notes;
+ DL = ED ? &ED->Notes : NULL;
else
continue;
PH.Advance();
- // default directive kind
+ // If a directive has been found but we're not interested
+ // in storing the directive information, return now.
+ if (!DL)
+ return true;
+
+ // Default directive kind.
bool RegexKind = false;
const char* KindStr = "string";
- // next optional token: -
+ // Next optional token: -
if (PH.Next("-re")) {
PH.Advance();
RegexKind = true;
KindStr = "regex";
}
- // skip optional whitespace
+ // Next optional token: @
+ SourceLocation ExpectedLoc;
+ if (!PH.Next("@")) {
+ ExpectedLoc = Pos;
+ } else {
+ PH.Advance();
+ unsigned Line = 0;
+ bool FoundPlus = PH.Next("+");
+ if (FoundPlus || PH.Next("-")) {
+ // Relative to current line.
+ PH.Advance();
+ bool Invalid = false;
+ unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid);
+ if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
+ if (FoundPlus) ExpectedLine += Line;
+ else ExpectedLine -= Line;
+ ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);
+ }
+ } else {
+ // Absolute line number.
+ if (PH.Next(Line) && Line > 0)
+ ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);
+ }
+
+ if (ExpectedLoc.isInvalid()) {
+ Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
+ diag::err_verify_missing_line) << KindStr;
+ continue;
+ }
+ PH.Advance();
+ }
+
+ // Skip optional whitespace.
PH.SkipWhitespace();
- // next optional token: positive integer or a '+'.
- unsigned Count = 1;
- if (PH.Next(Count))
+ // Next optional token: positive integer or a '+'.
+ unsigned Min = 1;
+ unsigned Max = 1;
+ if (PH.Next(Min)) {
PH.Advance();
- else if (PH.Next("+")) {
- Count = Directive::OneOrMoreCount;
+ // A positive integer can be followed by a '+' meaning min
+ // or more, or by a '-' meaning a range from min to max.
+ if (PH.Next("+")) {
+ Max = Directive::MaxCount;
+ PH.Advance();
+ } else if (PH.Next("-")) {
+ PH.Advance();
+ if (!PH.Next(Max) || Max < Min) {
+ Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
+ diag::err_verify_invalid_range) << KindStr;
+ continue;
+ }
+ PH.Advance();
+ } else {
+ Max = Min;
+ }
+ } else if (PH.Next("+")) {
+ // '+' on its own means "1 or more".
+ Max = Directive::MaxCount;
PH.Advance();
}
- // skip optional whitespace
+ // Skip optional whitespace.
PH.SkipWhitespace();
- // next token: {{
+ // Next token: {{
if (!PH.Next("{{")) {
- PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin),
- diag::err_verify_missing_start) << KindStr;
+ Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
+ diag::err_verify_missing_start) << KindStr;
continue;
}
PH.Advance();
const char* const ContentBegin = PH.C; // mark content begin
- // search for token: }}
+ // Search for token: }}
if (!PH.Search("}}")) {
- PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin),
- diag::err_verify_missing_end) << KindStr;
+ Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
+ diag::err_verify_missing_end) << KindStr;
continue;
}
const char* const ContentEnd = PH.P; // mark content end
PH.Advance();
- // build directive text; convert \n to newlines
+ // Build directive text; convert \n to newlines.
std::string Text;
StringRef NewlineStr = "\\n";
StringRef Content(ContentBegin, ContentEnd-ContentBegin);
@@ -325,25 +379,83 @@ static void ParseDirective(const char *CommentStart, unsigned CommentLen,
if (Text.empty())
Text.assign(ContentBegin, ContentEnd);
- // construct new directive
- Directive *D = Directive::Create(RegexKind, Pos, Text, Count);
+ // Construct new directive.
+ Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text,
+ Min, Max);
std::string Error;
- if (D->isValid(Error))
+ if (D->isValid(Error)) {
DL->push_back(D);
- else {
- PP.Diag(Pos.getLocWithOffset(ContentBegin-PH.Begin),
- diag::err_verify_invalid_content)
+ FoundDirective = true;
+ } else {
+ Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin),
+ diag::err_verify_invalid_content)
<< KindStr << Error;
}
}
+
+ return FoundDirective;
}
-/// FindExpectedDiags - Lex the main source file to find all of the
-// expected errors and warnings.
-static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) {
+/// HandleComment - Hook into the preprocessor and extract comments containing
+/// expected errors and warnings.
+bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
+ SourceRange Comment) {
+ SourceManager &SM = PP.getSourceManager();
+ SourceLocation CommentBegin = Comment.getBegin();
+
+ const char *CommentRaw = SM.getCharacterData(CommentBegin);
+ StringRef C(CommentRaw, SM.getCharacterData(Comment.getEnd()) - CommentRaw);
+
+ if (C.empty())
+ return false;
+
+ // Fold any "\<EOL>" sequences
+ size_t loc = C.find('\\');
+ if (loc == StringRef::npos) {
+ ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics());
+ return false;
+ }
+
+ std::string C2;
+ C2.reserve(C.size());
+
+ for (size_t last = 0;; loc = C.find('\\', last)) {
+ if (loc == StringRef::npos || loc == C.size()) {
+ C2 += C.substr(last);
+ break;
+ }
+ C2 += C.substr(last, loc-last);
+ last = loc + 1;
+
+ if (C[last] == '\n' || C[last] == '\r') {
+ ++last;
+
+ // Escape \r\n or \n\r, but not \n\n.
+ if (last < C.size())
+ if (C[last] == '\n' || C[last] == '\r')
+ if (C[last] != C[last-1])
+ ++last;
+ } else {
+ // This was just a normal backslash.
+ C2 += '\\';
+ }
+ }
+
+ if (!C2.empty())
+ ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics());
+ return false;
+}
+
+#ifndef NDEBUG
+/// \brief Lex the specified source file to determine whether it contains
+/// any expected-* directives. As a Lexer is used rather than a full-blown
+/// Preprocessor, directives inside skipped #if blocks will still be found.
+///
+/// \return true if any directives were found.
+static bool findDirectives(const Preprocessor &PP, FileID FID) {
// Create a raw lexer to pull all the comments out of FID.
if (FID.isInvalid())
- return;
+ return false;
SourceManager& SM = PP.getSourceManager();
// Create a lexer to lex all the tokens of the main file in raw mode.
@@ -355,6 +467,7 @@ static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) {
Token Tok;
Tok.setKind(tok::comment);
+ bool Found = false;
while (Tok.isNot(tok::eof)) {
RawLex.Lex(Tok);
if (!Tok.is(tok::comment)) continue;
@@ -363,19 +476,19 @@ static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) {
if (Comment.empty()) continue;
// Find all expected errors/warnings/notes.
- ParseDirective(&Comment[0], Comment.size(), ED, PP, Tok.getLocation());
- };
+ Found |= ParseDirective(Comment, 0, SM, Tok.getLocation(),
+ PP.getDiagnostics());
+ }
+ return Found;
}
-
-/// 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(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
- const_diag_iterator diag_begin,
- const_diag_iterator diag_end,
- const char *Kind, bool Expected) {
+#endif // !NDEBUG
+
+/// \brief Takes a list of diagnostics that have been generated but not matched
+/// by an expected-* directive and produces a diagnostic to the user from this.
+static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
+ const_diag_iterator diag_begin,
+ const_diag_iterator diag_end,
+ const char *Kind) {
if (diag_begin == diag_end) return 0;
SmallString<256> Fmt;
@@ -388,30 +501,32 @@ static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
OS << ": " << I->second;
}
- Diags.Report(diag::err_verify_inconsistent_diags)
- << Kind << !Expected << OS.str();
+ Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
+ << Kind << /*Unexpected=*/true << OS.str();
return std::distance(diag_begin, diag_end);
}
-static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
- DirectiveList &DL, const char *Kind,
- bool Expected) {
+/// \brief Takes a list of diagnostics that were expected to have been generated
+/// but were not and produces a diagnostic to the user from this.
+static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
+ DirectiveList &DL, const char *Kind) {
if (DL.empty())
return 0;
SmallString<256> Fmt;
llvm::raw_svector_ostream OS(Fmt);
for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
- Directive& D = **I;
- if (D.Location.isInvalid() || !SourceMgr)
- OS << "\n (frontend)";
- else
- OS << "\n Line " << SourceMgr->getPresumedLineNumber(D.Location);
+ Directive &D = **I;
+ OS << "\n Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
+ if (D.DirectiveLoc != D.DiagnosticLoc)
+ OS << " (directive at "
+ << SourceMgr.getFilename(D.DirectiveLoc) << ":"
+ << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ")";
OS << ": " << D.Text;
}
- Diags.Report(diag::err_verify_inconsistent_diags)
- << Kind << !Expected << OS.str();
+ Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
+ << Kind << /*Unexpected=*/false << OS.str();
return DL.size();
}
@@ -428,10 +543,9 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
Directive& D = **I;
- unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location);
- bool FoundOnce = false;
+ unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
- for (unsigned i = 0; i < D.Count; ++i) {
+ for (unsigned i = 0; i < D.Max; ++i) {
DiagList::iterator II, IE;
for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
@@ -439,29 +553,22 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
continue;
const std::string &RightText = II->second;
- if (D.Match(RightText))
+ if (D.match(RightText))
break;
}
if (II == IE) {
- if (D.Count == D.OneOrMoreCount) {
- if (!FoundOnce)
- LeftOnly.push_back(*I);
- // We are only interested in at least one match, so exit the loop.
- break;
- }
// Not found.
+ if (i >= D.Min) break;
LeftOnly.push_back(*I);
} else {
// Found. The same cannot be found twice.
Right.erase(II);
- FoundOnce = true;
}
}
}
// Now all that's left in Right are those that were not matched.
- unsigned num = PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true);
- num += PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(),
- Label, false);
+ unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label);
+ num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);
return num;
}
@@ -495,8 +602,6 @@ static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
}
void VerifyDiagnosticConsumer::CheckDiagnostics() {
- ExpectedData ED;
-
// Ensure any diagnostics go to the primary client.
bool OwnsCurClient = Diags.ownsClient();
DiagnosticConsumer *CurClient = Diags.takeClient();
@@ -506,32 +611,38 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
// markers. If not then any diagnostics are unexpected.
if (CurrentPreprocessor) {
SourceManager &SM = CurrentPreprocessor->getSourceManager();
- // Extract expected-error strings from main file.
- FindExpectedDiags(*CurrentPreprocessor, ED, SM.getMainFileID());
- // Only check for expectations in other diagnostic locations
- // if they are not the main file (via ID or FileEntry) - the main
- // file has already been looked at, and its expectations must not
- // be added twice.
- if (!FirstErrorFID.isInvalid() && FirstErrorFID != SM.getMainFileID()
- && (!SM.getFileEntryForID(FirstErrorFID)
- || (SM.getFileEntryForID(FirstErrorFID) !=
- SM.getFileEntryForID(SM.getMainFileID())))) {
- FindExpectedDiags(*CurrentPreprocessor, ED, FirstErrorFID);
- FirstErrorFID = FileID();
+
+#ifndef NDEBUG
+ // In a debug build, scan through any files that may have been missed
+ // during parsing and issue a fatal error if directives are contained
+ // within these files. If a fatal error occurs, this suggests that
+ // this file is being parsed separately from the main file.
+ HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
+ for (FilesWithDiagnosticsSet::iterator I = FilesWithDiagnostics.begin(),
+ End = FilesWithDiagnostics.end();
+ I != End; ++I) {
+ const FileEntry *E = SM.getFileEntryForID(*I);
+ // Don't check files already parsed or those handled as modules.
+ if (E && (FilesParsedForDirectives.count(E)
+ || HS.findModuleForHeader(E)))
+ continue;
+
+ if (findDirectives(*CurrentPreprocessor, *I))
+ llvm::report_fatal_error(Twine("-verify directives found after rather"
+ " than during normal parsing of ",
+ StringRef(E ? E->getName() : "(unknown)")));
}
+#endif
// Check that the expected diagnostics occurred.
NumErrors += CheckResults(Diags, SM, *Buffer, ED);
} 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));
+ NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),
+ Buffer->err_end(), "error") +
+ PrintUnexpected(Diags, 0, Buffer->warn_begin(),
+ Buffer->warn_end(), "warn") +
+ PrintUnexpected(Diags, 0, Buffer->note_begin(),
+ Buffer->note_end(), "note"));
}
Diags.takeClient();
@@ -539,6 +650,9 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
// Reset the buffer, we have processed all the diagnostics in it.
Buffer.reset(new TextDiagnosticBuffer());
+ ED.Errors.clear();
+ ED.Warnings.clear();
+ ED.Notes.clear();
}
DiagnosticConsumer *
@@ -549,9 +663,10 @@ VerifyDiagnosticConsumer::clone(DiagnosticsEngine &Diags) const {
return new VerifyDiagnosticConsumer(Diags);
}
-Directive* Directive::Create(bool RegexKind, const SourceLocation &Location,
- const std::string &Text, unsigned Count) {
+Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
+ SourceLocation DiagnosticLoc, StringRef Text,
+ unsigned Min, unsigned Max) {
if (RegexKind)
- return new RegexDirective(Location, Text, Count);
- return new StandardDirective(Location, Text, Count);
+ return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
+ return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
}
diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp
index ec5fde0..b7d4a3b 100644
--- a/lib/Frontend/Warnings.cpp
+++ b/lib/Frontend/Warnings.cpp
@@ -53,7 +53,11 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);
Diags.setShowOverloads(
static_cast<DiagnosticsEngine::OverloadsShown>(Opts.ShowOverloads));
-
+
+ Diags.setElideType(Opts.ElideType);
+ Diags.setPrintTemplateTree(Opts.ShowTemplateTree);
+ Diags.setShowColors(Opts.ShowColors);
+
// Handle -ferror-limit
if (Opts.ErrorLimit)
Diags.setErrorLimit(Opts.ErrorLimit);
@@ -83,6 +87,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
bool SetDiagnostic = (Report == 0);
for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i) {
StringRef Opt = Opts.Warnings[i];
+ StringRef OrigOpt = Opts.Warnings[i];
// Treat -Wformat=0 as an alias for -Wno-format.
if (Opt == "format=0")
@@ -130,7 +135,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
if ((Opt[5] != '=' && Opt[5] != '-') || Opt.size() == 6) {
if (Report)
Diags.Report(diag::warn_unknown_warning_specifier)
- << "-Werror" << ("-W" + Opt.str());
+ << "-Werror" << ("-W" + OrigOpt.str());
continue;
}
Specifier = Opt.substr(6);
@@ -158,7 +163,7 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
if ((Opt[12] != '=' && Opt[12] != '-') || Opt.size() == 13) {
if (Report)
Diags.Report(diag::warn_unknown_warning_specifier)
- << "-Wfatal-errors" << ("-W" + Opt.str());
+ << "-Wfatal-errors" << ("-W" + OrigOpt.str());
continue;
}
Specifier = Opt.substr(13);
@@ -182,7 +187,8 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags,
if (Report) {
if (DiagIDs->getDiagnosticsInGroup(Opt, _Diags))
- EmitUnknownDiagWarning(Diags, "-W", Opt, isPositive);
+ EmitUnknownDiagWarning(Diags, isPositive ? "-W" : "-Wno-", Opt,
+ isPositive);
} else {
Diags.setDiagnosticGroupMapping(Opt, Mapping);
}
OpenPOWER on IntegriCloud