diff options
author | dim <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
commit | 611ba3ea3300b71eb95dc4e45f20eee5dddd32e1 (patch) | |
tree | 2097d084eb235c0b12c0bff3445f4ec7bbaa8a12 /lib/Frontend | |
parent | c49018d9cce52d8c9f34b44865ec3ba8e89a1488 (diff) | |
download | FreeBSD-src-611ba3ea3300b71eb95dc4e45f20eee5dddd32e1.zip FreeBSD-src-611ba3ea3300b71eb95dc4e45f20eee5dddd32e1.tar.gz |
Vendor import of clang trunk r135360:
http://llvm.org/svn/llvm-project/cfe/trunk@135360
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 85 | ||||
-rw-r--r-- | lib/Frontend/BoostConAction.cpp | 39 | ||||
-rw-r--r-- | lib/Frontend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Frontend/CacheTokens.cpp | 7 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 123 | ||||
-rw-r--r-- | lib/Frontend/DependencyFile.cpp | 55 | ||||
-rw-r--r-- | lib/Frontend/FrontendAction.cpp | 46 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 217 | ||||
-rw-r--r-- | lib/Frontend/InitPreprocessor.cpp | 170 | ||||
-rw-r--r-- | lib/Frontend/PrintPreprocessedOutput.cpp | 48 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticPrinter.cpp | 115 |
12 files changed, 680 insertions, 229 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 8827116..5b0a52c 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -102,7 +102,7 @@ ASTUnit::ASTUnit(bool _MainFileIsAST) ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0), ShouldCacheCodeCompletionResults(false), - NestedMacroInstantiations(true), + NestedMacroExpansions(true), CompletionCacheTopLevelHashValue(0), PreambleTopLevelHashValue(0), CurrentTopLevelHashValue(0), @@ -182,6 +182,10 @@ static unsigned getDeclShowContexts(NamedDecl *ND, // all types are available due to functional casts. if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND)) Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); + + // In Objective-C, you can only be a subclass of another Objective-C class + if (isa<ObjCInterfaceDecl>(ND)) + Contexts |= (1 << (CodeCompletionContext::CCC_ObjCSuperclass - 1)); // Deal with tag names. if (isa<EnumDecl>(ND)) { @@ -208,6 +212,8 @@ static unsigned getDeclShowContexts(NamedDecl *ND, | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); } else if (isa<ObjCProtocolDecl>(ND)) { Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1)); + } else if (isa<ObjCCategoryDecl>(ND)) { + Contexts = (1 << (CodeCompletionContext::CCC_ObjCCategoryName - 1)); } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1)); @@ -928,8 +934,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts(); - PreprocessorOpts.DetailedRecordIncludesNestedMacroInstantiations - = NestedMacroInstantiations; + PreprocessorOpts.DetailedRecordIncludesNestedMacroExpansions + = NestedMacroExpansions; std::string PriorImplicitPCHInclude; if (OverrideMainBuffer) { PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer); @@ -1150,16 +1156,19 @@ static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old, /// buffer that should be used in place of the main file when doing so. /// Otherwise, returns a NULL pointer. llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( - CompilerInvocation PreambleInvocation, + const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild, unsigned MaxLines) { - FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts(); + + llvm::IntrusiveRefCntPtr<CompilerInvocation> + PreambleInvocation(new CompilerInvocation(PreambleInvocationIn)); + FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts(); PreprocessorOptions &PreprocessorOpts - = PreambleInvocation.getPreprocessorOpts(); + = PreambleInvocation->getPreprocessorOpts(); bool CreatedPreambleBuffer = false; std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble - = ComputePreamble(PreambleInvocation, MaxLines, CreatedPreambleBuffer); + = ComputePreamble(*PreambleInvocation, MaxLines, CreatedPreambleBuffer); // If ComputePreamble() Take ownership of the llvm::OwningPtr<llvm::MemoryBuffer> OwnedPreambleBuffer; @@ -1260,7 +1269,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // have occurred in the preamble. getDiagnostics().Reset(); ProcessWarningOptions(getDiagnostics(), - PreambleInvocation.getDiagnosticOpts()); + PreambleInvocation->getDiagnosticOpts()); getDiagnostics().setNumWarnings(NumWarningsInPreamble); if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble) StoredDiagnostics.erase( @@ -1357,7 +1366,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(Clang.get()); - Clang->setInvocation(&PreambleInvocation); + Clang->setInvocation(&*PreambleInvocation); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second; // Set up diagnostics, capturing all of the diagnostics produced. @@ -1716,7 +1725,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, bool PrecompilePreamble, bool CompleteTranslationUnit, bool CacheCodeCompletionResults, - bool NestedMacroInstantiations) { + bool NestedMacroExpansions) { // Create the AST unit. llvm::OwningPtr<ASTUnit> AST; AST.reset(new ASTUnit(false)); @@ -1727,7 +1736,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, AST->CompleteTranslationUnit = CompleteTranslationUnit; AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; AST->Invocation = CI; - AST->NestedMacroInstantiations = NestedMacroInstantiations; + AST->NestedMacroExpansions = NestedMacroExpansions; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> @@ -1753,7 +1762,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, bool CacheCodeCompletionResults, bool CXXPrecompilePreamble, bool CXXChainedPCH, - bool NestedMacroInstantiations) { + bool NestedMacroExpansions) { if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object // with the default options. @@ -1820,7 +1829,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size(); AST->StoredDiagnostics.swap(StoredDiagnostics); AST->Invocation = CI; - AST->NestedMacroInstantiations = NestedMacroInstantiations; + AST->NestedMacroExpansions = NestedMacroExpansions; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> @@ -1899,7 +1908,7 @@ namespace { /// results from an ASTUnit with the code-completion results provided to it, /// then passes the result on to class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer { - unsigned NormalContexts; + unsigned long long NormalContexts; ASTUnit &AST; CodeCompleteConsumer &Next; @@ -1913,22 +1922,24 @@ namespace { // Compute the set of contexts in which we will look when we don't have // any information about the specific context. NormalContexts - = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) - | (1 << (CodeCompletionContext::CCC_Statement - 1)) - | (1 << (CodeCompletionContext::CCC_Expression - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) - | (1 << (CodeCompletionContext::CCC_MemberAccess - 1)) - | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1)) - | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1)) - | (1 << (CodeCompletionContext::CCC_Recovery - 1)); + = (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)); if (AST.getASTContext().getLangOptions().CPlusPlus) - NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1)) - | (1 << (CodeCompletionContext::CCC_UnionTag - 1)) - | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)); + NormalContexts |= (1LL << (CodeCompletionContext::CCC_EnumTag - 1)) + | (1LL << (CodeCompletionContext::CCC_UnionTag - 1)) + | (1LL << (CodeCompletionContext::CCC_ClassOrStructTag - 1)); } virtual void ProcessCodeCompleteResults(Sema &S, @@ -1966,12 +1977,15 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context, case CodeCompletionContext::CCC_Statement: case CodeCompletionContext::CCC_Expression: case CodeCompletionContext::CCC_ObjCMessageReceiver: - case CodeCompletionContext::CCC_MemberAccess: + case CodeCompletionContext::CCC_DotMemberAccess: + case CodeCompletionContext::CCC_ArrowMemberAccess: + case CodeCompletionContext::CCC_ObjCPropertyAccess: case CodeCompletionContext::CCC_Namespace: case CodeCompletionContext::CCC_Type: case CodeCompletionContext::CCC_Name: case CodeCompletionContext::CCC_PotentiallyQualifiedName: case CodeCompletionContext::CCC_ParenthesizedExpression: + case CodeCompletionContext::CCC_ObjCSuperclass: break; case CodeCompletionContext::CCC_EnumTag: @@ -1990,6 +2004,9 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context, case CodeCompletionContext::CCC_TypeQualifiers: case CodeCompletionContext::CCC_Other: case CodeCompletionContext::CCC_OtherWithMacros: + case CodeCompletionContext::CCC_ObjCInstanceMessage: + case CodeCompletionContext::CCC_ObjCClassMessage: + case CodeCompletionContext::CCC_ObjCCategoryName: // We're looking for nothing, or we're looking for names that cannot // be hidden. return; @@ -2284,9 +2301,9 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, } } -bool ASTUnit::Save(llvm::StringRef File) { - if (getDiagnostics().hasErrorOccurred()) - return true; +CXSaveError ASTUnit::Save(llvm::StringRef File) { + if (getDiagnostics().hasUnrecoverableErrorOccurred()) + return CXSaveError_TranslationErrors; // FIXME: Can we somehow regenerate the stat cache here, or do we need to // unconditionally create a stat cache when we parse the file? @@ -2294,11 +2311,11 @@ bool ASTUnit::Save(llvm::StringRef File) { llvm::raw_fd_ostream Out(File.str().c_str(), ErrorInfo, llvm::raw_fd_ostream::F_Binary); if (!ErrorInfo.empty() || Out.has_error()) - return true; + return CXSaveError_Unknown; serialize(Out); Out.close(); - return Out.has_error(); + return Out.has_error()? CXSaveError_Unknown : CXSaveError_None; } bool ASTUnit::serialize(llvm::raw_ostream &OS) { diff --git a/lib/Frontend/BoostConAction.cpp b/lib/Frontend/BoostConAction.cpp deleted file mode 100644 index 4a12ff2..0000000 --- a/lib/Frontend/BoostConAction.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===-- BoostConAction.cpp - BoostCon Workshop Action -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#include "clang/Frontend/FrontendActions.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include <cstdio> -#include <iostream> -using namespace clang; - -namespace { - class BoostConASTConsumer : public ASTConsumer, - public RecursiveASTVisitor<BoostConASTConsumer> { - public: - /// HandleTranslationUnit - This method is called when the ASTs for entire - /// translation unit have been parsed. - virtual void HandleTranslationUnit(ASTContext &Ctx); - - bool VisitCXXRecordDecl(CXXRecordDecl *D) { - std::cout << D->getNameAsString() << std::endl; - return true; - } - }; -} - -ASTConsumer *BoostConAction::CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile) { - return new BoostConASTConsumer(); -} - -void BoostConASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { - fprintf(stderr, "Welcome to BoostCon!\n"); - TraverseDecl(Ctx.getTranslationUnitDecl()); -} diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 7dcbebf..556b133 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -12,7 +12,6 @@ add_clang_library(clangFrontend ASTConsumers.cpp ASTMerge.cpp ASTUnit.cpp - BoostConAction.cpp CacheTokens.cpp CompilerInstance.cpp CompilerInvocation.cpp diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 06a1fd2..20b5189 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -247,17 +247,16 @@ void PTHWriter::EmitToken(const Token& T) { } else { // We cache *un-cleaned* spellings. This gives us 100% fidelity with the // source code. - const char* s = T.getLiteralData(); - unsigned len = T.getLength(); + llvm::StringRef s(T.getLiteralData(), T.getLength()); // Get the string entry. - llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s, s+len); + llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s); // If this is a new string entry, bump the PTH offset. if (!E->getValue().hasOffset()) { E->getValue().setOffset(CurStrOffset); StrEntries.push_back(E); - CurStrOffset += len + 1; + CurStrOffset += s.size() + 1; } // Emit the relative offset into the PTH file for the spelling string. diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 38fcfe3..c58e3af 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -38,6 +38,7 @@ #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/system_error.h" +#include "llvm/Config/config.h" using namespace clang; CompilerInstance::CompilerInstance() @@ -228,7 +229,7 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, if (PPOpts.DetailedRecord) PP->createPreprocessingRecord( - PPOpts.DetailedRecordIncludesNestedMacroInstantiations); + PPOpts.DetailedRecordIncludesNestedMacroExpansions); InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 536512a..06b7260 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -123,6 +123,10 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-dwarf-debug-flags"); Res.push_back(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) @@ -133,6 +137,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-fno-common"); if (Opts.ForbidGuardVariables) Res.push_back("-fforbid-guard-variables"); + if (Opts.UseRegisterSizedBitfieldAccess) + Res.push_back("-fuse-register-sized-bitfield-access"); if (Opts.NoImplicitFloat) Res.push_back("-no-implicit-float"); if (Opts.OmitLeafFramePointer) @@ -169,6 +175,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-fno-use-cxa-atexit"); if (Opts.CXXCtorDtorAliases) Res.push_back("-mconstructor-aliases"); + if (Opts.ObjCAutoRefCountExceptions) + Res.push_back("-fobjc-arc-eh"); if (!Opts.DebugPass.empty()) { Res.push_back("-mdebug-pass"); Res.push_back(Opts.DebugPass); @@ -199,6 +207,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-mregparm"); Res.push_back(llvm::utostr(Opts.NumRegisterParameters)); } + if (Opts.NoExecStack) + Res.push_back("-mnoexecstack"); if (Opts.RelaxAll) Res.push_back("-mrelax-all"); if (Opts.SaveTempLabels) @@ -351,7 +361,6 @@ static const char *getActionName(frontend::ActionKind Kind) { case frontend::ASTDumpXML: return "-ast-dump-xml"; case frontend::ASTPrint: return "-ast-print"; case frontend::ASTView: return "-ast-view"; - case frontend::BoostCon: return "-boostcon"; case frontend::CreateModule: return "-create-module"; case frontend::DumpRawTokens: return "-dump-raw-tokens"; case frontend::DumpTokens: return "-dump-tokens"; @@ -413,6 +422,23 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-version"); if (Opts.FixWhatYouCan) Res.push_back("-fix-what-you-can"); + switch (Opts.ARCMTAction) { + case FrontendOptions::ARCMT_None: + break; + case FrontendOptions::ARCMT_Check: + Res.push_back("-arcmt-check"); + break; + case FrontendOptions::ARCMT_Modify: + Res.push_back("-arcmt-modify"); + break; + case FrontendOptions::ARCMT_Migrate: + Res.push_back("-arcmt-migrate"); + break; + } + if (!Opts.ARCMTMigrateDir.empty()) { + Res.push_back("-arcmt-migrate-directory"); + Res.push_back(Opts.ARCMTMigrateDir); + } bool NeedLang = false; for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) @@ -537,6 +563,8 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, Res.push_back("-nostdinc"); if (!Opts.UseStandardCXXIncludes) Res.push_back("-nostdinc++"); + if (Opts.UseLibcxx) + Res.push_back("-stdlib=libc++"); if (Opts.Verbose) Res.push_back("-v"); } @@ -670,8 +698,12 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fobjc-gc-only"); } } - if (Opts.ObjCInferRelatedResultType) - Res.push_back("-fobjc-infer-related-result-type"); + if (Opts.ObjCAutoRefCount) + Res.push_back("-fobjc-arc"); + if (Opts.ObjCRuntimeHasWeak) + Res.push_back("-fobjc-runtime-has-weak"); + if (!Opts.ObjCInferRelatedResultType) + Res.push_back("-fno-objc-infer-related-result-type"); if (Opts.AppleKext) Res.push_back("-fapple-kext"); @@ -705,6 +737,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-ffake-address-space-map"); if (Opts.ParseUnknownAnytype) Res.push_back("-funknown-anytype"); + if (Opts.DebuggerSupport) + Res.push_back("-fdebugger-support"); if (Opts.DelayedTemplateParsing) Res.push_back("-fdelayed-template-parsing"); if (Opts.Deprecated) @@ -938,6 +972,8 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables); + Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( + OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); @@ -951,6 +987,9 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize); 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.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit); Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases); Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model); @@ -965,6 +1004,7 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = Args.getLastArgIntValue(OPT_mregparm, 0, Diags); + Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer); Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels); @@ -1010,6 +1050,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, Opts.UsePhonyTargets = Args.hasArg(OPT_MP); Opts.ShowHeaderIncludes = Args.hasArg(OPT_H); Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file); + Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG); } static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, @@ -1117,8 +1158,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::ASTPrint; break; case OPT_ast_view: Opts.ProgramAction = frontend::ASTView; break; - case OPT_boostcon: - Opts.ProgramAction = frontend::BoostCon; break; case OPT_dump_raw_tokens: Opts.ProgramAction = frontend::DumpRawTokens; break; case OPT_dump_tokens: @@ -1220,6 +1259,26 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can); Opts.Modules = Args.getAllArgValues(OPT_import_module); + Opts.ARCMTAction = FrontendOptions::ARCMT_None; + if (const Arg *A = Args.getLastArg(OPT_arcmt_check, + OPT_arcmt_modify, + OPT_arcmt_migrate)) { + switch (A->getOption().getID()) { + default: + llvm_unreachable("missed a case"); + case OPT_arcmt_check: + Opts.ARCMTAction = FrontendOptions::ARCMT_Check; + break; + case OPT_arcmt_modify: + Opts.ARCMTAction = FrontendOptions::ARCMT_Modify; + break; + case OPT_arcmt_migrate: + Opts.ARCMTAction = FrontendOptions::ARCMT_Migrate; + break; + } + } + Opts.ARCMTMigrateDir = Args.getLastArgValue(OPT_arcmt_migrate_directory); + InputKind DashX = IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { DashX = llvm::StringSwitch<InputKind>(A->getValue(Args)) @@ -1291,13 +1350,15 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc); Opts.UseStandardIncludes = !Args.hasArg(OPT_nostdinc); Opts.UseStandardCXXIncludes = !Args.hasArg(OPT_nostdincxx); + if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) + Opts.UseLibcxx = (strcmp(A->getValue(Args), "libc++") == 0); Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); // Add -I... and -F... options in order. for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(Args), frontend::Angled, true, - /*IsFramework=*/ (*it)->getOption().matches(OPT_F), true); + /*IsFramework=*/ (*it)->getOption().matches(OPT_F), false); // Add -iprefix/-iwith-prefix/-iwithprefixbefore options. llvm::StringRef Prefix = ""; // FIXME: This isn't the correct default prefix. @@ -1309,24 +1370,24 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Prefix = A->getValue(Args); else if (A->getOption().matches(OPT_iwithprefix)) Opts.AddPath(Prefix.str() + A->getValue(Args), - frontend::System, false, false, true); + frontend::System, false, false, false); else Opts.AddPath(Prefix.str() + A->getValue(Args), - frontend::Angled, false, false, true); + frontend::Angled, false, false, false); } for (arg_iterator it = Args.filtered_begin(OPT_idirafter), ie = Args.filtered_end(); it != ie; ++it) - Opts.AddPath((*it)->getValue(Args), frontend::After, true, false, true); + Opts.AddPath((*it)->getValue(Args), frontend::After, true, false, false); for (arg_iterator it = Args.filtered_begin(OPT_iquote), ie = Args.filtered_end(); it != ie; ++it) - Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, true); + Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, false); for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem, OPT_isystem, OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(Args), ((*it)->getOption().matches(OPT_cxx_isystem) ? frontend::CXXSystem : frontend::System), - true, false, (*it)->getOption().matches(OPT_iwithsysroot)); + true, false, !(*it)->getOption().matches(OPT_iwithsysroot)); // FIXME: Need options for the various environment variables! } @@ -1480,17 +1541,27 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fno_operator_names)) Opts.CXXOperatorNames = 0; + if (Opts.ObjC1) { + if (Args.hasArg(OPT_fobjc_gc_only)) + Opts.setGCMode(LangOptions::GCOnly); + else if (Args.hasArg(OPT_fobjc_gc)) + Opts.setGCMode(LangOptions::HybridGC); + else if (Args.hasArg(OPT_fobjc_arc)) { + Opts.ObjCAutoRefCount = 1; + if (!Args.hasArg(OPT_fobjc_nonfragile_abi)) + Diags.Report(diag::err_arc_nonfragile_abi); + } + + if (Args.hasArg(OPT_fobjc_runtime_has_weak)) + Opts.ObjCRuntimeHasWeak = 1; + + if (Args.hasArg(OPT_fno_objc_infer_related_result_type)) + Opts.ObjCInferRelatedResultType = 0; + } + if (Args.hasArg(OPT_fgnu89_inline)) Opts.GNUInline = 1; - if (Args.hasArg(OPT_fobjc_gc_only)) - Opts.setGCMode(LangOptions::GCOnly); - else if (Args.hasArg(OPT_fobjc_gc)) - Opts.setGCMode(LangOptions::HybridGC); - - if (Args.hasArg(OPT_fobjc_infer_related_result_type)) - Opts.ObjCInferRelatedResultType = 1; - if (Args.hasArg(OPT_fapple_kext)) { if (!Opts.CPlusPlus) Diags.Report(diag::warn_c_kext); @@ -1598,6 +1669,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.MRTD = Args.hasArg(OPT_mrtd); Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); + Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support); // Record whether the __DEPRECATED define was requested. Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro, @@ -1715,6 +1787,19 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.addRemappedFile(Split.first, Split.second); } + + if (Arg *A = Args.getLastArg(OPT_fobjc_arc_cxxlib_EQ)) { + llvm::StringRef Name = A->getValue(Args); + unsigned Library = llvm::StringSwitch<unsigned>(Name) + .Case("libc++", ARCXX_libcxx) + .Case("libstdc++", ARCXX_libstdcxx) + .Case("none", ARCXX_nolib) + .Default(~0U); + if (Library == ~0U) + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + else + Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; + } } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index 5c3a231..1edd09b 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -17,9 +17,11 @@ #include "clang/Frontend/DependencyOutputOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/DirectoryLookup.h" +#include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -33,9 +35,11 @@ class DependencyFileCallback : public PPCallbacks { llvm::raw_ostream *OS; bool IncludeSystemHeaders; bool PhonyTarget; + bool AddMissingHeaderDeps; private: bool FileMatchesDepCriteria(const char *Filename, SrcMgr::CharacteristicKind FileType); + void AddFilename(llvm::StringRef Filename); void OutputDependencyFile(); public: @@ -44,10 +48,19 @@ public: const DependencyOutputOptions &Opts) : PP(_PP), Targets(Opts.Targets), OS(_OS), IncludeSystemHeaders(Opts.IncludeSystemHeaders), - PhonyTarget(Opts.UsePhonyTargets) {} + PhonyTarget(Opts.UsePhonyTargets), + AddMissingHeaderDeps(Opts.AddMissingHeaderDeps) {} virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType); + virtual void InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, + llvm::StringRef FileName, + bool IsAngled, + const FileEntry *File, + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath); virtual void EndOfMainFile() { OutputDependencyFile(); @@ -72,6 +85,16 @@ void clang::AttachDependencyFileGen(Preprocessor &PP, return; } + // Disable the "file not found" diagnostic if the -MG option was given. + // FIXME: Ideally this would live in the driver, but we don't have the ability + // to remap individual diagnostics there without creating a DiagGroup, in + // which case we would need to prevent the group name from showing up in + // diagnostics. + if (Opts.AddMissingHeaderDeps) { + PP.getDiagnostics().setDiagnosticMapping(diag::warn_pp_file_not_found, + diag::MAP_IGNORE, SourceLocation()); + } + PP.addPPCallbacks(new DependencyFileCallback(&PP, OS, Opts)); } @@ -103,14 +126,34 @@ void DependencyFileCallback::FileChanged(SourceLocation Loc, SM.getFileEntryForID(SM.getFileID(SM.getInstantiationLoc(Loc))); if (FE == 0) return; - const char *Filename = FE->getName(); - if (!FileMatchesDepCriteria(Filename, FileType)) + llvm::StringRef Filename = FE->getName(); + if (!FileMatchesDepCriteria(Filename.data(), FileType)) return; - // Remove leading "./" - if (Filename[0] == '.' && Filename[1] == '/') - Filename = &Filename[2]; + // Remove leading "./" (or ".//" or "././" etc.) + while (Filename.size() > 2 && Filename[0] == '.' && + llvm::sys::path::is_separator(Filename[1])) { + Filename = Filename.substr(1); + while (llvm::sys::path::is_separator(Filename[0])) + Filename = Filename.substr(1); + } + + AddFilename(Filename); +} + +void DependencyFileCallback::InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, + llvm::StringRef FileName, + bool IsAngled, + const FileEntry *File, + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { + if (AddMissingHeaderDeps && !File) + AddFilename(FileName); +} +void DependencyFileCallback::AddFilename(llvm::StringRef Filename) { if (FilesSet.insert(Filename)) Files.push_back(Filename); } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 42da44c..0128d6e 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -130,6 +130,9 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, setCurrentFile(Filename, InputKind); setCompilerInstance(&CI); + if (!BeginInvocation(CI)) + goto failure; + // AST files follow a very different path, since they share objects via the // AST unit. if (InputKind == IK_AST) { @@ -381,3 +384,46 @@ PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) { llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!"); } + +ASTConsumer *WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) { + return WrappedAction->CreateASTConsumer(CI, InFile); +} +bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) { + return WrappedAction->BeginInvocation(CI); +} +bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename) { + WrappedAction->setCurrentFile(getCurrentFile(), getCurrentFileKind()); + WrappedAction->setCompilerInstance(&CI); + return WrappedAction->BeginSourceFileAction(CI, Filename); +} +void WrapperFrontendAction::ExecuteAction() { + WrappedAction->ExecuteAction(); +} +void WrapperFrontendAction::EndSourceFileAction() { + WrappedAction->EndSourceFileAction(); +} + +bool WrapperFrontendAction::usesPreprocessorOnly() const { + return WrappedAction->usesPreprocessorOnly(); +} +bool WrapperFrontendAction::usesCompleteTranslationUnit() { + return WrappedAction->usesCompleteTranslationUnit(); +} +bool WrapperFrontendAction::hasPCHSupport() const { + return WrappedAction->hasPCHSupport(); +} +bool WrapperFrontendAction::hasASTFileSupport() const { + return WrappedAction->hasASTFileSupport(); +} +bool WrapperFrontendAction::hasIRSupport() const { + return WrappedAction->hasIRSupport(); +} +bool WrapperFrontendAction::hasCodeCompletionSupport() const { + return WrappedAction->hasCodeCompletionSupport(); +} + +WrapperFrontendAction::WrapperFrontendAction(FrontendAction *WrappedAction) + : WrappedAction(WrappedAction) {} + diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index ad93116..e11a415 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -45,7 +45,7 @@ class InitHeaderSearch { std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath; typedef std::vector<std::pair<IncludeDirGroup, DirectoryLookup> >::const_iterator path_iterator; - HeaderSearch& Headers; + HeaderSearch &Headers; bool Verbose; std::string IncludeSysroot; bool IsNotEmptyOrRoot; @@ -78,7 +78,8 @@ public: /// AddMinGW64CXXPaths - Add the necessary paths to support /// libstdc++ of x86_64-w64-mingw32 aka mingw-w64. - void AddMinGW64CXXPaths(llvm::StringRef Base); + void AddMinGW64CXXPaths(llvm::StringRef Base, + llvm::StringRef Version); /// AddDelimitedPaths - Add a list of paths delimited by the system PATH /// separator. The processing follows that of the CPATH variable for gcc. @@ -90,7 +91,8 @@ public: // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when // compiling c++. - void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple); + void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, + const HeaderSearchOptions &HSOpts); /// AddDefaultSystemIncludePaths - Adds the default system include paths so /// that e.g. stdio.h is found. @@ -103,7 +105,7 @@ public: void Realize(const LangOptions &Lang); }; -} +} // end anonymous namespace. void InitHeaderSearch::AddPath(const llvm::Twine &Path, IncludeDirGroup Group, bool isCXXAware, @@ -216,12 +218,16 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base, CXXSystem, true, false, false); } -void InitHeaderSearch::AddMinGW64CXXPaths(llvm::StringRef Base) { - AddPath(Base, +void InitHeaderSearch::AddMinGW64CXXPaths(llvm::StringRef Base, + llvm::StringRef Version) { + // Assumes Base is HeaderSearchOpts' ResourceDir + AddPath(Base + "/../../../include/c++/" + Version, + CXXSystem, true, false, false); + AddPath(Base + "/../../../include/c++/" + Version + "/x86_64-w64-mingw32", CXXSystem, true, false, false); - AddPath(Base + "/x86_64-w64-mingw32", + AddPath(Base + "/../../../include/c++/" + Version + "/i686-w64-mingw32", CXXSystem, true, false, false); - AddPath(Base + "/backward", + AddPath(Base + "/../../../include/c++/" + Version + "/backward", CXXSystem, true, false, false); } @@ -245,24 +251,23 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, DWORD valueSize = maxLength - 1; long lResult; bool returnValue = false; + if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { hRootKey = HKEY_CLASSES_ROOT; subKey = keyPath + 18; - } - else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { + } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { hRootKey = HKEY_USERS; subKey = keyPath + 11; - } - else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { + } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { hRootKey = HKEY_LOCAL_MACHINE; subKey = keyPath + 19; - } - else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { + } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { hRootKey = HKEY_CURRENT_USER; subKey = keyPath + 18; } else - return(false); + return false; + const char *placeHolder = strstr(subKey, "$VERSION"); char bestName[256]; bestName[0] = '\0'; @@ -338,7 +343,7 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName, RegCloseKey(hKey); } } - return(returnValue); + return returnValue; } #else // _MSC_VER // Read registry string. @@ -351,12 +356,12 @@ static bool getSystemRegistryString(const char*, const char*, char*, size_t) { static bool getVisualStudioDir(std::string &path) { // First check the environment variables that vsvars32.bat sets. const char* vcinstalldir = getenv("VCINSTALLDIR"); - if(vcinstalldir) { + if (vcinstalldir) { char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); if (p) *p = '\0'; path = vcinstalldir; - return(true); + return true; } char vsIDEInstallDir[256]; @@ -374,56 +379,52 @@ static bool getVisualStudioDir(std::string &path) { if (p) *p = '\0'; path = vsIDEInstallDir; - return(true); + return true; } - else if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { + + if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); if (p) *p = '\0'; path = vsExpressIDEInstallDir; - return(true); + return true; } - else { - // Try the environment. - const char* vs100comntools = getenv("VS100COMNTOOLS"); - const char* vs90comntools = getenv("VS90COMNTOOLS"); - const char* vs80comntools = getenv("VS80COMNTOOLS"); - const char* vscomntools = NULL; - - // Try to find the version that we were compiled with - if(false) {} - #if (_MSC_VER >= 1600) // VC100 - else if(vs100comntools) { - vscomntools = vs100comntools; - } - #elif (_MSC_VER == 1500) // VC80 - else if(vs90comntools) { - vscomntools = vs90comntools; - } - #elif (_MSC_VER == 1400) // VC80 - else if(vs80comntools) { - vscomntools = vs80comntools; - } - #endif - // Otherwise find any version we can - else if (vs100comntools) - vscomntools = vs100comntools; - else if (vs90comntools) - vscomntools = vs90comntools; - else if (vs80comntools) - vscomntools = vs80comntools; - - if (vscomntools && *vscomntools) { - char *p = const_cast<char *>(strstr(vscomntools, "\\Common7\\Tools")); - if (p) - *p = '\0'; - path = vscomntools; - return(true); - } - else - return(false); + + // Try the environment. + const char *vs100comntools = getenv("VS100COMNTOOLS"); + const char *vs90comntools = getenv("VS90COMNTOOLS"); + const char *vs80comntools = getenv("VS80COMNTOOLS"); + const char *vscomntools = NULL; + + // Try to find the version that we were compiled with + if(false) {} + #if (_MSC_VER >= 1600) // VC100 + else if(vs100comntools) { + vscomntools = vs100comntools; } - return(false); + #elif (_MSC_VER == 1500) // VC80 + else if(vs90comntools) { + vscomntools = vs90comntools; + } + #elif (_MSC_VER == 1400) // VC80 + else if(vs80comntools) { + vscomntools = vs80comntools; + } + #endif + // Otherwise find any version we can + else if (vs100comntools) + vscomntools = vs100comntools; + else if (vs90comntools) + vscomntools = vs90comntools; + else if (vs80comntools) + vscomntools = vs80comntools; + + if (vscomntools && *vscomntools) { + const char *p = strstr(vscomntools, "\\Common7\\Tools"); + path = p ? std::string(vscomntools, p) : vscomntools; + return true; + } + return false; } // Get Windows SDK installation directory. @@ -432,7 +433,9 @@ static bool getWindowsSDKDir(std::string &path) { // Try the Windows registry. bool hasSDKDir = getSystemRegistryString( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", - "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1); + "InstallationFolder", + windowsSDKInstallDir, + sizeof(windowsSDKInstallDir) - 1); // If we have both vc80 and vc90, pick version we were compiled with. if (hasSDKDir && windowsSDKInstallDir[0]) { path = windowsSDKInstallDir; @@ -548,17 +551,28 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, AddPath("/boot/develop/headers/posix", System, true, false, false); AddPath("/boot/develop/headers", System, true, false, false); break; + case llvm::Triple::RTEMS: + break; case llvm::Triple::Cygwin: AddPath("/usr/include/w32api", System, true, false, false); break; - case llvm::Triple::MinGW32: - // FIXME: We should be aware of i686-w64-mingw32. - if (triple.getArch() == llvm::Triple::x86_64) - AddPath("c:/mingw/x86_64-w64-mingw32/include", - System, true, false, false); - AddPath("/mingw/include", System, true, false, false); - AddPath("c:/mingw/include", System, true, false, false); + case llvm::Triple::MinGW32: { + // mingw-w64 crt include paths + llvm::sys::Path P(HSOpts.ResourceDir); + P.appendComponent("../../../i686-w64-mingw32/include"); // <sysroot>/i686-w64-mingw32/include + AddPath(P.str(), System, true, false, false); + P = llvm::sys::Path(HSOpts.ResourceDir); + P.appendComponent("../../../x86_64-w64-mingw32/include"); // <sysroot>/x86_64-w64-mingw32/include + AddPath(P.str(), System, true, false, false); + // mingw.org crt include paths + P = llvm::sys::Path(HSOpts.ResourceDir); + P.appendComponent("../../../include"); // <sysroot>/include + AddPath(P.str(), System, true, false, false); + AddPath("/mingw/include", System, true, false, false); + AddPath("c:/mingw/include", System, true, false, false); + } break; + case llvm::Triple::Linux: // Generic Debian multiarch support: if (triple.getArch() == llvm::Triple::x86_64) { @@ -576,11 +590,12 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, break; } - AddPath("/usr/include", System, false, false, false); + if ( os != llvm::Triple::RTEMS ) + AddPath("/usr/include", System, false, false, false); } void InitHeaderSearch:: -AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { +AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT); if (CxxIncludeRoot != "") { @@ -640,20 +655,19 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "3.4.4"); break; case llvm::Triple::MinGW32: - // FIXME: We should be aware of i686-w64-mingw32. - if (triple.getArch() == llvm::Triple::x86_64) { - // mingw-w64-20110207 - AddMinGW64CXXPaths("c:/mingw/x86_64-w64-mingw32/include/c++/4.5.3"); - // mingw-w64-20101129 - AddMinGW64CXXPaths("c:/mingw/x86_64-w64-mingw32/include/c++/4.5.2"); - } - // Try gcc 4.5.2 (MSYS) - AddMinGWCPlusPlusIncludePaths("/mingw/lib/gcc", "mingw32", "4.5.2"); - // Try gcc 4.5.0 + // mingw-w64 C++ include paths (i686-w64-mingw32 and x86_64-w64-mingw32) + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.0"); + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.1"); + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.2"); + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.5.3"); + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.6.0"); + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.6.1"); + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.6.2"); + AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.0"); + // mingw.org C++ include paths + AddMinGWCPlusPlusIncludePaths("/mingw/lib/gcc", "mingw32", "4.5.2"); //MSYS AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0"); - // Try gcc 4.4.0 AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0"); - // Try gcc 4.3.0 AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0"); break; case llvm::Triple::DragonFly: @@ -733,6 +747,9 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { "x86_64-redhat-linux", "32", "", triple); AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.5.1", "i686-redhat-linux", "", "", triple); + // RHEL5(gcc44) + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4", + "x86_64-redhat-linux6E", "32", "", triple); // Fedora 13 AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.4", "x86_64-redhat-linux", "32", "", triple); @@ -814,6 +831,10 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { "x86_64-unknown-linux-gnu", "", "", triple); // Arch Linux gcc 4.6 + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.1", + "i686-pc-linux-gnu", "", "", triple); + AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.1", + "x86_64-unknown-linux-gnu", "", "", triple); AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0", "i686-pc-linux-gnu", "", "", triple); AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.6.0", @@ -918,8 +939,12 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { - if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) - AddDefaultCPlusPlusIncludePaths(triple); + if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) { + if (HSOpts.UseLibcxx) + AddPath("/usr/include/c++/v1", CXXSystem, true, false, false); + else + AddDefaultCPlusPlusIncludePaths(triple, HSOpts); + } AddDefaultCIncludePaths(triple, HSOpts); @@ -1017,23 +1042,24 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) { std::vector<DirectoryLookup> SearchList; SearchList.reserve(IncludePath.size()); - /* Quoted arguments go first. */ + // Quoted arguments go first. for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); it != ie; ++it) { if (it->first == Quoted) SearchList.push_back(it->second); } - /* Deduplicate and remember index */ + // Deduplicate and remember index. RemoveDuplicates(SearchList, 0, Verbose); - unsigned quoted = SearchList.size(); + unsigned NumQuoted = SearchList.size(); for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); it != ie; ++it) { if (it->first == Angled) SearchList.push_back(it->second); } - RemoveDuplicates(SearchList, quoted, Verbose); - unsigned angled = SearchList.size(); + + RemoveDuplicates(SearchList, NumQuoted, Verbose); + unsigned NumAngled = SearchList.size(); for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); it != ie; ++it) { @@ -1047,16 +1073,19 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) { SearchList.push_back(it->second); } - RemoveDuplicates(SearchList, angled, Verbose); + // Remove duplicates across both the Angled and System directories. GCC does + // this and failing to remove duplicates across these two groups breaks + // #include_next. + RemoveDuplicates(SearchList, NumQuoted, Verbose); bool DontSearchCurDir = false; // TODO: set to true if -I- is set? - Headers.SetSearchPaths(SearchList, quoted, angled, DontSearchCurDir); + Headers.SetSearchPaths(SearchList, NumQuoted, NumAngled, DontSearchCurDir); // If verbose, print the list of directories that will be searched. if (Verbose) { llvm::errs() << "#include \"...\" search starts here:\n"; for (unsigned i = 0, e = SearchList.size(); i != e; ++i) { - if (i == quoted) + if (i == NumQuoted) llvm::errs() << "#include <...> search starts here:\n"; const char *Name = SearchList[i].getName(); const char *Suffix; @@ -1084,7 +1113,7 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) { const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i]; Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework, - !E.IsSysRootRelative); + E.IgnoreSysRoot); } // Add entries from CPATH and friends. diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 147a8df0..9428cd5 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -221,6 +221,125 @@ static void DefineExactWidthIntType(TargetInfo::IntType Ty, ConstSuffix); } +/// \brief Add definitions required for a smooth interaction between +/// Objective-C++ automatic reference counting and libc++. +static void AddObjCXXARCLibcxxDefines(const LangOptions &LangOpts, + MacroBuilder &Builder) { + Builder.defineMacro("_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF"); + + std::string Result; + { + // Provide overloads of the function std::__1::addressof() that accept + // references to lifetime-qualified objects. libc++'s (more general) + // std::__1::addressof() template fails to instantiate with such types, + // because it attempts to convert the object to a char& before + // dereferencing. + llvm::raw_string_ostream Out(Result); + + Out << "#pragma clang diagnostic push\n" + << "#pragma clang diagnostic ignored \"-Wc++0x-extensions\"\n" + << "namespace std { inline namespace __1 {\n" + << "\n"; + + Out << "template <class _Tp>\n" + << "inline __attribute__ ((__visibility__(\"hidden\"), " + << "__always_inline__))\n" + << "__attribute__((objc_ownership(strong))) _Tp*\n" + << "addressof(__attribute__((objc_ownership(strong))) _Tp& __x) {\n" + << " return &__x;\n" + << "}\n" + << "\n"; + + if (LangOpts.ObjCRuntimeHasWeak) { + Out << "template <class _Tp>\n" + << "inline __attribute__ ((__visibility__(\"hidden\")," + << "__always_inline__))\n" + << "__attribute__((objc_ownership(weak))) _Tp*\n" + << "addressof(__attribute__((objc_ownership(weak))) _Tp& __x) {\n" + << " return &__x;\n" + << "};\n" + << "\n"; + } + + Out << "template <class _Tp>\n" + << "inline __attribute__ ((__visibility__(\"hidden\")," + << "__always_inline__))\n" + << "__attribute__((objc_ownership(autoreleasing))) _Tp*\n" + << "addressof(__attribute__((objc_ownership(autoreleasing))) _Tp& __x) " + << "{\n" + << " return &__x;\n" + << "}\n" + << "\n"; + + Out << "template <class _Tp>\n" + << "inline __attribute__ ((__visibility__(\"hidden\"), " + << "__always_inline__))\n" + << "__unsafe_unretained _Tp* addressof(__unsafe_unretained _Tp& __x)" + << " {\n" + << " return &__x;\n" + << "}\n"; + + Out << "\n" + << "} }\n" + << "#pragma clang diagnostic pop\n" + << "\n"; + } + Builder.append(Result); +} + +/// \brief Add definitions required for a smooth interaction between +/// Objective-C++ automated reference counting and libstdc++ (4.2). +static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, + MacroBuilder &Builder) { + Builder.defineMacro("_GLIBCXX_PREDEFINED_OBJC_ARC_IS_SCALAR"); + + std::string Result; + { + // Provide specializations for the __is_scalar type trait so that + // lifetime-qualified objects are not considered "scalar" types, which + // libstdc++ uses as an indicator of the presence of trivial copy, assign, + // default-construct, and destruct semantics (none of which hold for + // lifetime-qualified objects in ARC). + llvm::raw_string_ostream Out(Result); + + Out << "namespace std {\n" + << "\n" + << "struct __true_type;\n" + << "struct __false_type;\n" + << "\n"; + + Out << "template<typename _Tp> struct __is_scalar;\n" + << "\n"; + + Out << "template<typename _Tp>\n" + << "struct __is_scalar<__attribute__((objc_ownership(strong))) _Tp> {\n" + << " enum { __value = 0 };\n" + << " typedef __false_type __type;\n" + << "};\n" + << "\n"; + + if (LangOpts.ObjCRuntimeHasWeak) { + Out << "template<typename _Tp>\n" + << "struct __is_scalar<__attribute__((objc_ownership(weak))) _Tp> {\n" + << " enum { __value = 0 };\n" + << " typedef __false_type __type;\n" + << "};\n" + << "\n"; + } + + Out << "template<typename _Tp>\n" + << "struct __is_scalar<__attribute__((objc_ownership(autoreleasing)))" + << " _Tp> {\n" + << " enum { __value = 0 };\n" + << " typedef __false_type __type;\n" + << "};\n" + << "\n"; + + Out << "}\n"; + } + Builder.append(Result); +} + static void InitializeStandardPredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, const FrontendOptions &FEOpts, @@ -240,11 +359,18 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, } else { if (LangOpts.GNUMode) Builder.defineMacro("__cplusplus"); - else - // C++ [cpp.predefined]p1: + 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. - Builder.defineMacro("__cplusplus", "199711L"); + else + Builder.defineMacro("__cplusplus", "199711L"); + } } if (LangOpts.ObjC1) @@ -312,7 +438,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // darwin_constant_cfstrings controls this. This is also dependent // on other things like the runtime I believe. This is set even for C code. - Builder.defineMacro("__CONSTANT_CFSTRINGS__"); + if (!LangOpts.NoConstantCFStrings) + Builder.defineMacro("__CONSTANT_CFSTRINGS__"); if (LangOpts.ObjC2) Builder.defineMacro("OBJC_NEW_PROPERTIES"); @@ -487,6 +614,15 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.FastRelaxedMath) Builder.defineMacro("__FAST_RELAXED_MATH__"); + if (LangOpts.ObjCAutoRefCount) { + Builder.defineMacro("__weak", "__attribute__((objc_ownership(weak)))"); + Builder.defineMacro("__strong", "__attribute__((objc_ownership(strong)))"); + Builder.defineMacro("__autoreleasing", + "__attribute__((objc_ownership(autoreleasing)))"); + Builder.defineMacro("__unsafe_unretained", + "__attribute__((objc_ownership(none)))"); + } + // Get other target #defines. TI.getTargetDefines(LangOpts, Builder); } @@ -560,6 +696,7 @@ void clang::InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &InitOpts, const HeaderSearchOptions &HSOpts, const FrontendOptions &FEOpts) { + const LangOptions &LangOpts = PP.getLangOptions(); std::string PredefineBuffer; PredefineBuffer.reserve(4080); llvm::raw_string_ostream Predefines(PredefineBuffer); @@ -575,10 +712,27 @@ void clang::InitializePreprocessor(Preprocessor &PP, Builder.append("# 1 \"<built-in>\" 3"); // Install things like __POWERPC__, __GNUC__, etc into the macro table. - if (InitOpts.UsePredefines) - InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(), - FEOpts, Builder); - + if (InitOpts.UsePredefines) { + InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, Builder); + + // Install definitions to make Objective-C++ ARC work well with various + // C++ Standard Library implementations. + if (LangOpts.ObjC1 && LangOpts.CPlusPlus && LangOpts.ObjCAutoRefCount) { + switch (InitOpts.ObjCXXARCStandardLibrary) { + case ARCXX_nolib: + break; + + case ARCXX_libcxx: + AddObjCXXARCLibcxxDefines(LangOpts, Builder); + break; + + case ARCXX_libstdcxx: + AddObjCXXARCLibstdcxxDefines(LangOpts, Builder); + break; + } + } + } + // Even with predefines off, some macros are still predefined. // These should all be defined in the preprocessor according to the // current language configuration. diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index b46e047..c892960 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" #include <cstdio> using namespace clang; @@ -122,6 +123,12 @@ public: virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, const std::string &Str); virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str); + virtual void PragmaDiagnosticPush(SourceLocation Loc, + llvm::StringRef Namespace); + virtual void PragmaDiagnosticPop(SourceLocation Loc, + llvm::StringRef Namespace); + virtual void PragmaDiagnostic(SourceLocation Loc, llvm::StringRef Namespace, + diag::Mapping Map, llvm::StringRef Str); bool HandleFirstTokOnLine(Token &Tok); bool MoveToLine(SourceLocation Loc) { @@ -189,7 +196,7 @@ bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { if (LineNo-CurLine == 1) OS << '\n'; else if (LineNo == CurLine) - return false; // Spelling line moved, but instantiation line didn't. + return false; // Spelling line moved, but expansion line didn't. else { const char *NewLines = "\n\n\n\n\n\n\n\n"; OS.write(NewLines, LineNo-CurLine); @@ -361,12 +368,49 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, EmittedTokensOnThisLine = true; } +void PrintPPOutputPPCallbacks:: +PragmaDiagnosticPush(SourceLocation Loc, llvm::StringRef Namespace) { + MoveToLine(Loc); + OS << "#pragma " << Namespace << " diagnostic push"; + EmittedTokensOnThisLine = true; +} + +void PrintPPOutputPPCallbacks:: +PragmaDiagnosticPop(SourceLocation Loc, llvm::StringRef Namespace) { + MoveToLine(Loc); + OS << "#pragma " << Namespace << " diagnostic pop"; + EmittedTokensOnThisLine = true; +} + +void PrintPPOutputPPCallbacks:: +PragmaDiagnostic(SourceLocation Loc, llvm::StringRef Namespace, + diag::Mapping Map, llvm::StringRef Str) { + MoveToLine(Loc); + OS << "#pragma " << Namespace << " diagnostic "; + switch (Map) { + default: llvm_unreachable("unexpected diagnostic kind"); + case diag::MAP_WARNING: + OS << "warning"; + break; + case diag::MAP_ERROR: + OS << "error"; + break; + case diag::MAP_IGNORE: + OS << "ignored"; + break; + case diag::MAP_FATAL: + OS << "fatal"; + break; + } + OS << " \"" << Str << '"'; + EmittedTokensOnThisLine = true; +} /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this /// is called for the first token on each new line. If this really is the start /// of a new logical line, handle it and return true, otherwise return false. /// This may not be the start of a logical line because the "start of line" -/// marker is set for spelling lines, not instantiation ones. +/// marker is set for spelling lines, not expansion ones. bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { // Figure out what line we went to and insert the appropriate number of // newline characters. diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 1c47bf7..e49e19a 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -292,8 +292,57 @@ static void SelectInterestingSourceRegion(std::string &SourceLine, } } -void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level, - SourceLocation Loc, +/// 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.isMacroArgInstantiation(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.isMacroArgInstantiation(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.getImmediateInstantiationRange(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.isMacroArgInstantiation(Loc)) + return SM.getImmediateInstantiationRange(Loc).first; + + // Otherwise, the callee of the macro is located where this location was + // spelled inside the macro definition. + return SM.getImmediateSpellingLoc(Loc); +} + +void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, CharSourceRange *Ranges, unsigned NumRanges, const SourceManager &SM, @@ -307,38 +356,46 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level, assert(!Loc.isInvalid() && "must have a valid source location here"); // If this is a macro ID, first emit information about where this was - // instantiated (recursively) then emit information about where the token was + // expanded (recursively) then emit information about where the token was // spelled from. if (!Loc.isFileID()) { - // Whether to suppress printing this macro instantiation. + // Whether to suppress printing this macro expansion. bool Suppressed = OnMacroInst >= MacroSkipStart && OnMacroInst < MacroSkipEnd; - - SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first; + // 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); + + SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); + // FIXME: Map ranges? - EmitCaretDiagnostic(Level, OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns, + EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, + Hints, NumHints, Columns, OnMacroInst + 1, MacroSkipStart, MacroSkipEnd); - + // Map the location. - Loc = SM.getImmediateSpellingLoc(Loc); + Loc = getImmediateMacroCalleeLoc(SM, Loc); // Map the ranges. for (unsigned i = 0; i != NumRanges; ++i) { CharSourceRange &R = Ranges[i]; SourceLocation S = R.getBegin(), E = R.getEnd(); if (S.isMacroID()) - R.setBegin(SM.getImmediateSpellingLoc(S)); + R.setBegin(getImmediateMacroCalleeLoc(SM, S)); if (E.isMacroID()) - R.setEnd(SM.getImmediateSpellingLoc(E)); + R.setEnd(getImmediateMacroCalleeLoc(SM, E)); } if (!Suppressed) { + // Don't print recursive expansion notes from an expansion note. + Loc = SM.getSpellingLoc(Loc); + // Get the pretty name, according to #line directives etc. PresumedLoc PLoc = SM.getPresumedLoc(Loc); if (PLoc.isInvalid()) return; - + // If this diagnostic is not in the main file, print out the // "included from" lines. if (LastWarningLoc != PLoc.getIncludeLoc()) { @@ -353,9 +410,9 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level, OS << PLoc.getColumn() << ':'; OS << ' '; } - OS << "note: instantiated from:\n"; - - EmitCaretDiagnostic(Level, Loc, Ranges, NumRanges, SM, Hints, NumHints, + OS << "note: expanded from:\n"; + + EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, 0, 0, Columns, OnMacroInst + 1, MacroSkipStart, MacroSkipEnd); return; @@ -364,13 +421,13 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level, if (OnMacroInst == MacroSkipStart) { // Tell the user that we've skipped contexts. OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart) - << " contexts in backtrace; use -fmacro-backtrace-limit=0 to see " + << " expansions in backtrace; use -fmacro-backtrace-limit=0 to see " "all)\n"; } return; } - + // Decompose the location into a FID/Offset pair. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); FileID FID = LocInfo.first; @@ -769,6 +826,20 @@ static bool PrintWordWrapped(llvm::raw_ostream &OS, return true; } +/// 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); +} + void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info) { // Default implementation (Warnings/errors count). @@ -787,7 +858,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, // if enabled. if (Info.getLocation().isValid()) { const SourceManager &SM = Info.getSourceManager(); - PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation()); + PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Info.getLocation()); if (PLoc.isInvalid()) { // At least print the file name if available: FileID FID = SM.getFileID(Info.getLocation()); @@ -1040,15 +1111,17 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, } } + const SourceManager &SM = LastLoc.getManager(); unsigned MacroInstSkipStart = 0, MacroInstSkipEnd = 0; if (DiagOpts && DiagOpts->MacroBacktraceLimit && !LastLoc.isFileID()) { - // Compute the length of the macro-instantiation backtrace, so that we + // Compute the length of the macro-expansion backtrace, so that we // can establish which steps in the macro backtrace we'll skip. SourceLocation Loc = LastLoc; unsigned Depth = 0; do { ++Depth; - Loc = LastLoc.getManager().getImmediateInstantiationRange(Loc).first; + Loc = skipToMacroArgExpansion(SM, Loc); + Loc = getImmediateMacroCallerLoc(SM, Loc); } while (!Loc.isFileID()); if (Depth > DiagOpts->MacroBacktraceLimit) { @@ -1058,7 +1131,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, } } - EmitCaretDiagnostic(Level, LastLoc, Ranges, NumRanges, LastLoc.getManager(), + EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(), Info.getFixItHints(), Info.getNumFixItHints(), DiagOpts->MessageLength, |