From bb52786da8d055568eef6e5694288c1258bc8c2a Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 12 Jul 2011 19:35:15 +0000 Subject: [PATCH] Implement -MG. Fixes PR9613 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134996 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticDriverKinds.td | 2 + include/clang/Basic/DiagnosticLexKinds.td | 2 +- include/clang/Driver/CC1Options.td | 1 + .../clang/Frontend/DependencyOutputOptions.h | 2 + lib/Driver/Tools.cpp | 10 ++++- lib/Frontend/CompilerInvocation.cpp | 1 + lib/Frontend/DependencyFile.cpp | 39 ++++++++++++++++++- lib/Lex/PPDirectives.cpp | 9 +++-- lib/Lex/Pragma.cpp | 2 +- test/Driver/mg.c | 5 +++ 10 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 test/Driver/mg.c diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 409c6a2016..e33b67ef7a 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -86,6 +86,8 @@ def err_drv_objc_gc_arr : Error< "cannot specify both '-fobjc-arc' and '%0'">; def err_arc_nonfragile_abi : Error< "-fobjc-arc is not supported with fragile abi">; +def err_drv_mg_requires_m_or_mm : Error< + "option '-MG' requires '-M' or '-MM'">; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for c++ and objective-c++ only">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 3514ccace2..38d6a80016 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -178,7 +178,7 @@ def ext_empty_fnmacro_arg : Extension< def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_hash_error : Error<"#error%0">; -def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; +def warn_pp_file_not_found : Warning<"'%0' file not found">, DefaultFatal; def err_pp_error_opening_file : Error< "error opening file '%0': %1">, DefaultFatal; def err_pp_empty_filename : Error<"empty filename">; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 6befc8cd07..8cadbe92da 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -208,6 +208,7 @@ def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">; def MT : Separate<"-MT">, HelpText<"Specify target for dependency">; def MP : Flag<"-MP">, HelpText<"Create phony target for each dependency (other than main file)">; +def MG : Flag<"-MG">, HelpText<"Add missing headers to dependency list">; //===----------------------------------------------------------------------===// // Diagnostic Options diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h index 35aa6c6aac..1e22c227fc 100644 --- a/include/clang/Frontend/DependencyOutputOptions.h +++ b/include/clang/Frontend/DependencyOutputOptions.h @@ -24,6 +24,7 @@ public: unsigned UsePhonyTargets : 1; ///< Include phony targets for each /// dependency, which can avoid some 'make' /// problems. + unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list /// The file to write dependency output to. std::string OutputFile; @@ -43,6 +44,7 @@ public: IncludeSystemHeaders = 0; ShowHeaderIncludes = 0; UsePhonyTargets = 0; + AddMissingHeaderDeps = 0; } }; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 9b3e49480e..eb17609d6c 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -242,6 +242,13 @@ void Clang::AddPreprocessingOptions(const Driver &D, CmdArgs.push_back("-sys-header-deps"); } + if (Args.hasArg(options::OPT_MG)) { + if (!A || A->getOption().matches(options::OPT_MD) || + A->getOption().matches(options::OPT_MMD)) + D.Diag(clang::diag::err_drv_mg_requires_m_or_mm); + CmdArgs.push_back("-MG"); + } + Args.AddLastArg(CmdArgs, options::OPT_MP); // Convert all -MQ args to -MT @@ -1354,8 +1361,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, types::ID InputType = Inputs[0].getType(); if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; - if ((Unsupported = Args.getLastArg(options::OPT_MG)) || - (Unsupported = Args.getLastArg(options::OPT_iframework))) + if ((Unsupported = Args.getLastArg(options::OPT_iframework))) D.Diag(clang::diag::err_drv_clang_unsupported) << Unsupported->getOption().getName(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 02a5088f93..05b3377b3e 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1048,6 +1048,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, diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index dde3454aba..1edd09b06c 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -17,6 +17,7 @@ #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" @@ -34,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: @@ -45,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(); @@ -73,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)); } @@ -116,7 +138,22 @@ void DependencyFileCallback::FileChanged(SourceLocation Loc, 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/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index efa188f752..4af5fabe5c 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1180,16 +1180,17 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, const FileEntry *File = LookupFile( Filename, isAngled, LookupFrom, CurDir, Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL); - if (File == 0) { - Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; - return; - } // Notify the callback object that we've seen an inclusion directive. if (Callbacks) Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File, End, SearchPath, RelativePath); + if (File == 0) { + Diag(FilenameTok, diag::warn_pp_file_not_found) << Filename; + return; + } + // The #included file will be considered to be a system header if either it is // in a system include directory, or if the #includer is a system include // header. diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index bd2ac1b6fb..e6b28c1331 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -368,7 +368,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) { const DirectoryLookup *CurDir; const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL, NULL); if (File == 0) { - Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; + Diag(FilenameTok, diag::warn_pp_file_not_found) << Filename; return; } diff --git a/test/Driver/mg.c b/test/Driver/mg.c new file mode 100644 index 0000000000..4f438142f4 --- /dev/null +++ b/test/Driver/mg.c @@ -0,0 +1,5 @@ +// RUN: %clang -M -MG -include nonexistent-preinclude.h %s > %t +// RUN: fgrep nonexistent-preinclude.h %t +// RUN: fgrep nonexistent-ppinclude.h %t + +#include "nonexistent-ppinclude.h" -- 2.40.0