Implement -Wunused-macros functionality.

llvm-svn: 38632
This commit is contained in:
Chris Lattner 2006-07-03 05:16:44 +00:00
parent cbd6d3e0ed
commit 13044d942d
4 changed files with 66 additions and 19 deletions

View File

@ -352,16 +352,14 @@ const FileEntry *Preprocessor::LookupFile(const std::string &Filename,
bool Preprocessor::isInPrimaryFile() const { bool Preprocessor::isInPrimaryFile() const {
unsigned NumLexersFound = 0; unsigned NumLexersFound = 0;
if (CurLexer && !CurLexer->Is_PragmaLexer) if (CurLexer && !CurLexer->Is_PragmaLexer)
++NumLexersFound; return CurLexer->isMainFile();
/// If there are any stacked lexers, we're in a #include. // If there are any stacked lexers, we're in a #include.
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i)
if (IncludeMacroStack[i].TheLexer) { if (IncludeMacroStack[i].TheLexer &&
if (!IncludeMacroStack[i].TheLexer->Is_PragmaLexer) !IncludeMacroStack[i].TheLexer->Is_PragmaLexer)
if (++NumLexersFound > 1) return IncludeMacroStack[i].TheLexer->isMainFile();
return false; return false;
}
return NumLexersFound < 2;
} }
/// getCurrentLexer - Return the current file lexer being lexed from. Note /// getCurrentLexer - Return the current file lexer being lexed from. Note
@ -384,7 +382,8 @@ Lexer *Preprocessor::getCurrentFileLexer() const {
/// start lexing tokens from it instead of the current buffer. Return true /// start lexing tokens from it instead of the current buffer. Return true
/// on failure. /// on failure.
void Preprocessor::EnterSourceFile(unsigned FileID, void Preprocessor::EnterSourceFile(unsigned FileID,
const DirectoryLookup *CurDir) { const DirectoryLookup *CurDir,
bool isMainFile) {
assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!"); assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!");
++NumEnteredSourceFiles; ++NumEnteredSourceFiles;
@ -393,6 +392,7 @@ void Preprocessor::EnterSourceFile(unsigned FileID,
const SourceBuffer *Buffer = SourceMgr.getBuffer(FileID); const SourceBuffer *Buffer = SourceMgr.getBuffer(FileID);
Lexer *TheLexer = new Lexer(Buffer, FileID, *this); Lexer *TheLexer = new Lexer(Buffer, FileID, *this);
if (isMainFile) TheLexer->setIsMainFile();
EnterSourceFileWithLexer(TheLexer, CurDir); EnterSourceFileWithLexer(TheLexer, CurDir);
} }
@ -490,6 +490,9 @@ void Preprocessor::RegisterBuiltinMacros() {
void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier, void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
MacroInfo *MI) { MacroInfo *MI) {
++NumMacroExpanded; ++NumMacroExpanded;
// Notice that this macro has been used.
MI->setIsUsed(true);
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially. // If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
if (MI->isBuiltinMacro()) if (MI->isBuiltinMacro())
@ -689,6 +692,18 @@ void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok) {
} }
} }
namespace {
struct UnusedIdentifierReporter : public IdentifierVisitor {
Preprocessor &PP;
UnusedIdentifierReporter(Preprocessor &pp) : PP(pp) {}
void VisitIdentifier(IdentifierTokenInfo &ITI) const {
if (ITI.getMacroInfo() && !ITI.getMacroInfo()->isUsed())
PP.Diag(ITI.getMacroInfo()->getDefinitionLoc(), diag::pp_macro_not_used);
}
};
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Lexer Event Handling. // Lexer Event Handling.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -775,6 +790,9 @@ void Preprocessor::HandleEndOfFile(LexerToken &Result, bool isEndOfMacro) {
// We're done with the #included file. // We're done with the #included file.
delete CurLexer; delete CurLexer;
CurLexer = 0; CurLexer = 0;
// This is the end of the top-level file.
IdentifierInfo.VisitIdentifiers(UnusedIdentifierReporter(*this));
} }
/// HandleEndOfMacro - This callback is invoked when the lexer hits the end of /// HandleEndOfMacro - This callback is invoked when the lexer hits the end of
@ -1302,10 +1320,17 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok) {
LexUnexpandedToken(Tok); LexUnexpandedToken(Tok);
} }
// If this is the primary source file, remember that this macro hasn't been
// used yet.
if (isInPrimaryFile())
MI->setIsUsed(false);
// Finally, if this identifier already had a macro defined for it, verify that // Finally, if this identifier already had a macro defined for it, verify that
// the macro bodies are identical and free the old definition. // the macro bodies are identical and free the old definition.
if (MacroInfo *OtherMI = MacroNameTok.getIdentifierInfo()->getMacroInfo()) { if (MacroInfo *OtherMI = MacroNameTok.getIdentifierInfo()->getMacroInfo()) {
if (!OtherMI->isUsed())
Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used);
// FIXME: Verify the definition is the same. // FIXME: Verify the definition is the same.
// Macros must be identical. This means all tokes and whitespace separation // Macros must be identical. This means all tokes and whitespace separation
// must be the same. // must be the same.
@ -1336,10 +1361,8 @@ void Preprocessor::HandleUndefDirective(LexerToken &UndefTok) {
// If the macro is not defined, this is a noop undef, just return. // If the macro is not defined, this is a noop undef, just return.
if (MI == 0) return; if (MI == 0) return;
#if 0 // FIXME: implement warn_unused_macros. if (!MI->isUsed())
if (CPP_OPTION (pfile, warn_unused_macros)) Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
_cpp_warn_if_unused_macro (pfile, node, NULL);
#endif
// Free macro definition. // Free macro definition.
delete MI; delete MI;

View File

@ -98,6 +98,8 @@ DIAG(pp_undef_builtin_macro, WARNING,
"undefining builtin macro") "undefining builtin macro")
DIAG(pp_redef_builtin_macro, WARNING, DIAG(pp_redef_builtin_macro, WARNING,
"redefining builtin macro") "redefining builtin macro")
DIAG(pp_macro_not_used, WARNING, // -Wunused-macros
"macro is not used")
DIAG(ext_pp_import_directive, EXTENSION, DIAG(ext_pp_import_directive, EXTENSION,
"#import is a language extension") "#import is a language extension")

View File

@ -33,30 +33,50 @@ class MacroInfo {
/// to. /// to.
std::vector<LexerToken> ReplacementTokens; std::vector<LexerToken> ReplacementTokens;
/// isDisabled - True if we have started an expansion of this macro already. /// IsDisabled - True if we have started an expansion of this macro already.
/// This disbles recursive expansion, which would be quite bad for things like /// This disbles recursive expansion, which would be quite bad for things like
/// #define A A. /// #define A A.
bool IsDisabled : 1; bool IsDisabled : 1;
/// isBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if /// IsBuiltinMacro - True if this is a builtin macro, such as __LINE__, and if
/// it has not yet been redefined or undefined. /// it has not yet been redefined or undefined.
bool IsBuiltinMacro : 1; bool IsBuiltinMacro : 1;
/// IsUsed - True if this macro is either defined in the main file and has
/// been used, or if it is not defined in the main file. This is used to
/// emit -Wunused-macros diagnostics.
bool IsUsed : 1;
public: public:
MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
IsDisabled = false; IsDisabled = false;
IsBuiltinMacro = false; IsBuiltinMacro = false;
IsUsed = true;
} }
/// getDefinitionLoc - Return the location that the macro was defined at.
///
SourceLocation getDefinitionLoc() const { return Location; }
/// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag. /// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag.
/// ///
void setIsBuiltinMacro(bool Val = true) { void setIsBuiltinMacro(bool Val = true) {
IsBuiltinMacro = Val; IsBuiltinMacro = Val;
} }
/// setIsUsed - Set the value of the IsUsed flag.
///
void setIsUsed(bool Val) {
IsUsed = Val;
}
/// isBuiltinMacro - Return true if this macro is a builtin macro, such as /// isBuiltinMacro - Return true if this macro is a builtin macro, such as
/// __LINE__, which requires processing before expansion. /// __LINE__, which requires processing before expansion.
bool isBuiltinMacro() const { return IsBuiltinMacro; } bool isBuiltinMacro() const { return IsBuiltinMacro; }
/// isUsed - Return false if this macro is defined in the main file and has
/// not yet been used.
bool isUsed() const { return IsUsed; }
/// getNumTokens - Return the number of tokens that this macro expands to. /// getNumTokens - Return the number of tokens that this macro expands to.
/// ///
unsigned getNumTokens() const { unsigned getNumTokens() const {

View File

@ -297,8 +297,10 @@ public:
const DirectoryLookup *&CurDir); const DirectoryLookup *&CurDir);
/// EnterSourceFile - Add a source file to the top of the include stack and /// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. /// start lexing tokens from it instead of the current buffer. If isMainFile
void EnterSourceFile(unsigned CurFileID, const DirectoryLookup *Dir); /// is true, this is the main file for the translation unit.
void EnterSourceFile(unsigned CurFileID, const DirectoryLookup *Dir,
bool isMainFile = false);
/// EnterMacro - Add a Macro to the top of the include stack and start lexing /// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer. /// tokens from it instead of the current buffer.
@ -440,7 +442,7 @@ private:
void Handle_Pragma(LexerToken &Tok); void Handle_Pragma(LexerToken &Tok);
/// EnterSourceFile - Add a source file to the top of the include stack and /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. /// start lexing tokens from it instead of the current buffer.
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);