forked from OSchip/llvm-project
PPCallbacks::MacroUndefined, change signature and add test.
Summary: The PPCallbacks::MacroUndefined callback is currently insufficient for clients that need to track the MacroDirectives. This patch adds an additional argument to PPCallbacks::MacroUndefined that is the undef MacroDirective. Reviewers: bruno, manmanren Reviewed By: bruno Subscribers: nemanjai, cfe-commits Differential Revision: https://reviews.llvm.org/D29923 llvm-svn: 301449
This commit is contained in:
parent
2074b67ec2
commit
b7755111a2
|
@ -247,10 +247,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Hook called whenever a macro \#undef is seen.
|
/// \brief Hook called whenever a macro \#undef is seen.
|
||||||
|
/// \param Token The active Token
|
||||||
|
/// \param MD A MacroDefinition for the named macro.
|
||||||
|
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
|
||||||
///
|
///
|
||||||
/// MD is released immediately following this callback.
|
/// MD is released immediately following this callback.
|
||||||
virtual void MacroUndefined(const Token &MacroNameTok,
|
virtual void MacroUndefined(const Token &MacroNameTok,
|
||||||
const MacroDefinition &MD) {
|
const MacroDefinition &MD,
|
||||||
|
const MacroDirective *Undef) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Hook called whenever the 'defined' operator is seen.
|
/// \brief Hook called whenever the 'defined' operator is seen.
|
||||||
|
@ -439,15 +443,17 @@ public:
|
||||||
Second->MacroExpands(MacroNameTok, MD, Range, Args);
|
Second->MacroExpands(MacroNameTok, MD, Range, Args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override {
|
void MacroDefined(const Token &MacroNameTok,
|
||||||
|
const MacroDirective *MD) override {
|
||||||
First->MacroDefined(MacroNameTok, MD);
|
First->MacroDefined(MacroNameTok, MD);
|
||||||
Second->MacroDefined(MacroNameTok, MD);
|
Second->MacroDefined(MacroNameTok, MD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroUndefined(const Token &MacroNameTok,
|
void MacroUndefined(const Token &MacroNameTok,
|
||||||
const MacroDefinition &MD) override {
|
const MacroDefinition &MD,
|
||||||
First->MacroUndefined(MacroNameTok, MD);
|
const MacroDirective *Undef) override {
|
||||||
Second->MacroUndefined(MacroNameTok, MD);
|
First->MacroUndefined(MacroNameTok, MD, Undef);
|
||||||
|
Second->MacroUndefined(MacroNameTok, MD, Undef);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
|
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||||
|
|
|
@ -488,7 +488,8 @@ namespace clang {
|
||||||
void MacroExpands(const Token &Id, const MacroDefinition &MD,
|
void MacroExpands(const Token &Id, const MacroDefinition &MD,
|
||||||
SourceRange Range, const MacroArgs *Args) override;
|
SourceRange Range, const MacroArgs *Args) override;
|
||||||
void MacroDefined(const Token &Id, const MacroDirective *MD) override;
|
void MacroDefined(const Token &Id, const MacroDirective *MD) override;
|
||||||
void MacroUndefined(const Token &Id, const MacroDefinition &MD) override;
|
void MacroUndefined(const Token &Id, const MacroDefinition &MD,
|
||||||
|
const MacroDirective *Undef) override;
|
||||||
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
|
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
|
||||||
StringRef FileName, bool IsAngled,
|
StringRef FileName, bool IsAngled,
|
||||||
CharSourceRange FilenameRange,
|
CharSourceRange FilenameRange,
|
||||||
|
|
|
@ -172,7 +172,8 @@ public:
|
||||||
|
|
||||||
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
|
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
|
||||||
void MacroUndefined(const Token &MacroNameTok,
|
void MacroUndefined(const Token &MacroNameTok,
|
||||||
const MacroDefinition &MD) override;
|
const MacroDefinition &MD,
|
||||||
|
const MacroDirective *Undef) override;
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
@ -389,7 +390,8 @@ void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
|
void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
|
||||||
const MacroDefinition &MD) {
|
const MacroDefinition &MD,
|
||||||
|
const MacroDirective *Undef) {
|
||||||
// Only print out macro definitions in -dD mode.
|
// Only print out macro definitions in -dD mode.
|
||||||
if (!DumpDefines) return;
|
if (!DumpDefines) return;
|
||||||
|
|
||||||
|
|
|
@ -2592,25 +2592,26 @@ void Preprocessor::HandleUndefDirective() {
|
||||||
// Okay, we have a valid identifier to undef.
|
// Okay, we have a valid identifier to undef.
|
||||||
auto *II = MacroNameTok.getIdentifierInfo();
|
auto *II = MacroNameTok.getIdentifierInfo();
|
||||||
auto MD = getMacroDefinition(II);
|
auto MD = getMacroDefinition(II);
|
||||||
|
UndefMacroDirective *Undef = nullptr;
|
||||||
|
|
||||||
|
// If the macro is not defined, this is a noop undef.
|
||||||
|
if (const MacroInfo *MI = MD.getMacroInfo()) {
|
||||||
|
if (!MI->isUsed() && MI->isWarnIfUnused())
|
||||||
|
Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
|
||||||
|
|
||||||
|
if (MI->isWarnIfUnused())
|
||||||
|
WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
|
||||||
|
|
||||||
|
Undef = AllocateUndefMacroDirective(MacroNameTok.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
// If the callbacks want to know, tell them about the macro #undef.
|
// If the callbacks want to know, tell them about the macro #undef.
|
||||||
// Note: no matter if the macro was defined or not.
|
// Note: no matter if the macro was defined or not.
|
||||||
if (Callbacks)
|
if (Callbacks)
|
||||||
Callbacks->MacroUndefined(MacroNameTok, MD);
|
Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
|
||||||
|
|
||||||
// If the macro is not defined, this is a noop undef, just return.
|
if (Undef)
|
||||||
const MacroInfo *MI = MD.getMacroInfo();
|
appendMacroDirective(II, Undef);
|
||||||
if (!MI)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!MI->isUsed() && MI->isWarnIfUnused())
|
|
||||||
Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
|
|
||||||
|
|
||||||
if (MI->isWarnIfUnused())
|
|
||||||
WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
|
|
||||||
|
|
||||||
appendMacroDirective(MacroNameTok.getIdentifierInfo(),
|
|
||||||
AllocateUndefMacroDirective(MacroNameTok.getLocation()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -422,7 +422,8 @@ void PreprocessingRecord::MacroDefined(const Token &Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreprocessingRecord::MacroUndefined(const Token &Id,
|
void PreprocessingRecord::MacroUndefined(const Token &Id,
|
||||||
const MacroDefinition &MD) {
|
const MacroDefinition &MD,
|
||||||
|
const MacroDirective *Undef) {
|
||||||
MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
|
MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,8 @@ public:
|
||||||
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
|
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
|
||||||
/// MI is released immediately following this callback.
|
/// MI is released immediately following this callback.
|
||||||
void MacroUndefined(const Token &MacroNameTok,
|
void MacroUndefined(const Token &MacroNameTok,
|
||||||
const MacroDefinition &MD) override {}
|
const MacroDefinition &MD,
|
||||||
|
const MacroDirective *UD) override {}
|
||||||
|
|
||||||
/// MacroExpands - This is called by when a macro invocation is found.
|
/// MacroExpands - This is called by when a macro invocation is found.
|
||||||
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||||
|
|
|
@ -249,12 +249,18 @@ TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct MacroAction {
|
struct MacroAction {
|
||||||
|
enum Kind { kExpansion, kDefinition, kUnDefinition};
|
||||||
|
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
std::string Name;
|
std::string Name;
|
||||||
bool isDefinition; // if false, it is expansion.
|
unsigned MAKind : 3;
|
||||||
|
|
||||||
MacroAction(SourceLocation Loc, StringRef Name, bool isDefinition)
|
MacroAction(SourceLocation Loc, StringRef Name, unsigned K)
|
||||||
: Loc(Loc), Name(Name), isDefinition(isDefinition) { }
|
: Loc(Loc), Name(Name), MAKind(K) { }
|
||||||
|
|
||||||
|
bool isExpansion() const { return MAKind == kExpansion; }
|
||||||
|
bool isDefinition() const { return MAKind & kDefinition; }
|
||||||
|
bool isUnDefinition() const { return MAKind & kUnDefinition; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroTracker : public PPCallbacks {
|
class MacroTracker : public PPCallbacks {
|
||||||
|
@ -267,13 +273,22 @@ public:
|
||||||
const MacroDirective *MD) override {
|
const MacroDirective *MD) override {
|
||||||
Macros.push_back(MacroAction(MD->getLocation(),
|
Macros.push_back(MacroAction(MD->getLocation(),
|
||||||
MacroNameTok.getIdentifierInfo()->getName(),
|
MacroNameTok.getIdentifierInfo()->getName(),
|
||||||
true));
|
MacroAction::kDefinition));
|
||||||
|
}
|
||||||
|
void MacroUndefined(const Token &MacroNameTok,
|
||||||
|
const MacroDefinition &MD,
|
||||||
|
const MacroDirective *UD) override {
|
||||||
|
Macros.push_back(
|
||||||
|
MacroAction(UD ? UD->getLocation() : SourceLocation(),
|
||||||
|
MacroNameTok.getIdentifierInfo()->getName(),
|
||||||
|
UD ? MacroAction::kDefinition | MacroAction::kUnDefinition
|
||||||
|
: MacroAction::kUnDefinition));
|
||||||
}
|
}
|
||||||
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||||
SourceRange Range, const MacroArgs *Args) override {
|
SourceRange Range, const MacroArgs *Args) override {
|
||||||
Macros.push_back(MacroAction(MacroNameTok.getLocation(),
|
Macros.push_back(MacroAction(MacroNameTok.getLocation(),
|
||||||
MacroNameTok.getIdentifierInfo()->getName(),
|
MacroNameTok.getIdentifierInfo()->getName(),
|
||||||
false));
|
MacroAction::kExpansion));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -281,7 +296,10 @@ public:
|
||||||
|
|
||||||
TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
|
TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
|
||||||
const char *header =
|
const char *header =
|
||||||
"#define MACRO_IN_INCLUDE 0\n";
|
"#define MACRO_IN_INCLUDE 0\n"
|
||||||
|
"#define MACRO_DEFINED\n"
|
||||||
|
"#undef MACRO_DEFINED\n"
|
||||||
|
"#undef MACRO_UNDEFINED\n";
|
||||||
|
|
||||||
const char *main =
|
const char *main =
|
||||||
"#define M(x) x\n"
|
"#define M(x) x\n"
|
||||||
|
@ -327,34 +345,46 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
|
||||||
// Make sure we got the tokens that we expected.
|
// Make sure we got the tokens that we expected.
|
||||||
ASSERT_EQ(0U, toks.size());
|
ASSERT_EQ(0U, toks.size());
|
||||||
|
|
||||||
ASSERT_EQ(9U, Macros.size());
|
ASSERT_EQ(15U, Macros.size());
|
||||||
// #define M(x) x
|
// #define M(x) x
|
||||||
ASSERT_TRUE(Macros[0].isDefinition);
|
ASSERT_TRUE(Macros[0].isDefinition());
|
||||||
ASSERT_EQ("M", Macros[0].Name);
|
ASSERT_EQ("M", Macros[0].Name);
|
||||||
// #define INC "/test-header.h"
|
// #define INC "/test-header.h"
|
||||||
ASSERT_TRUE(Macros[1].isDefinition);
|
ASSERT_TRUE(Macros[1].isDefinition());
|
||||||
ASSERT_EQ("INC", Macros[1].Name);
|
ASSERT_EQ("INC", Macros[1].Name);
|
||||||
// M expansion in #include M(INC)
|
// M expansion in #include M(INC)
|
||||||
ASSERT_FALSE(Macros[2].isDefinition);
|
ASSERT_FALSE(Macros[2].isDefinition());
|
||||||
ASSERT_EQ("M", Macros[2].Name);
|
ASSERT_EQ("M", Macros[2].Name);
|
||||||
// INC expansion in #include M(INC)
|
// INC expansion in #include M(INC)
|
||||||
ASSERT_FALSE(Macros[3].isDefinition);
|
ASSERT_TRUE(Macros[3].isExpansion());
|
||||||
ASSERT_EQ("INC", Macros[3].Name);
|
ASSERT_EQ("INC", Macros[3].Name);
|
||||||
// #define MACRO_IN_INCLUDE 0
|
// #define MACRO_IN_INCLUDE 0
|
||||||
ASSERT_TRUE(Macros[4].isDefinition);
|
ASSERT_TRUE(Macros[4].isDefinition());
|
||||||
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[4].Name);
|
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[4].Name);
|
||||||
|
// #define MACRO_DEFINED
|
||||||
|
ASSERT_TRUE(Macros[5].isDefinition());
|
||||||
|
ASSERT_FALSE(Macros[5].isUnDefinition());
|
||||||
|
ASSERT_EQ("MACRO_DEFINED", Macros[5].Name);
|
||||||
|
// #undef MACRO_DEFINED
|
||||||
|
ASSERT_TRUE(Macros[6].isDefinition());
|
||||||
|
ASSERT_TRUE(Macros[6].isUnDefinition());
|
||||||
|
ASSERT_EQ("MACRO_DEFINED", Macros[6].Name);
|
||||||
|
// #undef MACRO_UNDEFINED
|
||||||
|
ASSERT_FALSE(Macros[7].isDefinition());
|
||||||
|
ASSERT_TRUE(Macros[7].isUnDefinition());
|
||||||
|
ASSERT_EQ("MACRO_UNDEFINED", Macros[7].Name);
|
||||||
// #define INC2 </test-header.h>
|
// #define INC2 </test-header.h>
|
||||||
ASSERT_TRUE(Macros[5].isDefinition);
|
ASSERT_TRUE(Macros[8].isDefinition());
|
||||||
ASSERT_EQ("INC2", Macros[5].Name);
|
ASSERT_EQ("INC2", Macros[8].Name);
|
||||||
// M expansion in #include M(INC2)
|
// M expansion in #include M(INC2)
|
||||||
ASSERT_FALSE(Macros[6].isDefinition);
|
ASSERT_FALSE(Macros[9].isDefinition());
|
||||||
ASSERT_EQ("M", Macros[6].Name);
|
ASSERT_EQ("M", Macros[9].Name);
|
||||||
// INC2 expansion in #include M(INC2)
|
// INC2 expansion in #include M(INC2)
|
||||||
ASSERT_FALSE(Macros[7].isDefinition);
|
ASSERT_TRUE(Macros[10].isExpansion());
|
||||||
ASSERT_EQ("INC2", Macros[7].Name);
|
ASSERT_EQ("INC2", Macros[10].Name);
|
||||||
// #define MACRO_IN_INCLUDE 0
|
// #define MACRO_IN_INCLUDE 0
|
||||||
ASSERT_TRUE(Macros[8].isDefinition);
|
ASSERT_TRUE(Macros[11].isDefinition());
|
||||||
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[8].Name);
|
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[11].Name);
|
||||||
|
|
||||||
// The INC expansion in #include M(INC) comes before the first
|
// The INC expansion in #include M(INC) comes before the first
|
||||||
// MACRO_IN_INCLUDE definition of the included file.
|
// MACRO_IN_INCLUDE definition of the included file.
|
||||||
|
@ -362,7 +392,7 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
|
||||||
|
|
||||||
// The INC2 expansion in #include M(INC2) comes before the second
|
// The INC2 expansion in #include M(INC2) comes before the second
|
||||||
// MACRO_IN_INCLUDE definition of the included file.
|
// MACRO_IN_INCLUDE definition of the included file.
|
||||||
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[7].Loc, Macros[8].Loc));
|
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue