Skip to content

Commit b775511

Browse files
author
Frederich Munch
committedApr 26, 2017
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
1 parent 2074b67 commit b775511

File tree

7 files changed

+88
-46
lines changed

7 files changed

+88
-46
lines changed
 

‎clang/include/clang/Lex/PPCallbacks.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,14 @@ class PPCallbacks {
247247
}
248248

249249
/// \brief Hook called whenever a macro \#undef is seen.
250+
/// \param Token The active Token
251+
/// \param MD A MacroDefinition for the named macro.
252+
/// \param Undef New MacroDirective if the macro was defined, null otherwise.
250253
///
251254
/// MD is released immediately following this callback.
252255
virtual void MacroUndefined(const Token &MacroNameTok,
253-
const MacroDefinition &MD) {
256+
const MacroDefinition &MD,
257+
const MacroDirective *Undef) {
254258
}
255259

256260
/// \brief Hook called whenever the 'defined' operator is seen.
@@ -439,15 +443,17 @@ class PPChainedCallbacks : public PPCallbacks {
439443
Second->MacroExpands(MacroNameTok, MD, Range, Args);
440444
}
441445

442-
void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override {
446+
void MacroDefined(const Token &MacroNameTok,
447+
const MacroDirective *MD) override {
443448
First->MacroDefined(MacroNameTok, MD);
444449
Second->MacroDefined(MacroNameTok, MD);
445450
}
446451

447452
void MacroUndefined(const Token &MacroNameTok,
448-
const MacroDefinition &MD) override {
449-
First->MacroUndefined(MacroNameTok, MD);
450-
Second->MacroUndefined(MacroNameTok, MD);
453+
const MacroDefinition &MD,
454+
const MacroDirective *Undef) override {
455+
First->MacroUndefined(MacroNameTok, MD, Undef);
456+
Second->MacroUndefined(MacroNameTok, MD, Undef);
451457
}
452458

453459
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,

‎clang/include/clang/Lex/PreprocessingRecord.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,8 @@ namespace clang {
488488
void MacroExpands(const Token &Id, const MacroDefinition &MD,
489489
SourceRange Range, const MacroArgs *Args) override;
490490
void MacroDefined(const Token &Id, const MacroDirective *MD) override;
491-
void MacroUndefined(const Token &Id, const MacroDefinition &MD) override;
491+
void MacroUndefined(const Token &Id, const MacroDefinition &MD,
492+
const MacroDirective *Undef) override;
492493
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
493494
StringRef FileName, bool IsAngled,
494495
CharSourceRange FilenameRange,

‎clang/lib/Frontend/PrintPreprocessedOutput.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
172172

173173
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
174174
void MacroUndefined(const Token &MacroNameTok,
175-
const MacroDefinition &MD) override;
175+
const MacroDefinition &MD,
176+
const MacroDirective *Undef) override;
176177
};
177178
} // end anonymous namespace
178179

@@ -389,7 +390,8 @@ void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
389390
}
390391

391392
void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
392-
const MacroDefinition &MD) {
393+
const MacroDefinition &MD,
394+
const MacroDirective *Undef) {
393395
// Only print out macro definitions in -dD mode.
394396
if (!DumpDefines) return;
395397

‎clang/lib/Lex/PPDirectives.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,25 +2592,26 @@ void Preprocessor::HandleUndefDirective() {
25922592
// Okay, we have a valid identifier to undef.
25932593
auto *II = MacroNameTok.getIdentifierInfo();
25942594
auto MD = getMacroDefinition(II);
2595+
UndefMacroDirective *Undef = nullptr;
2596+
2597+
// If the macro is not defined, this is a noop undef.
2598+
if (const MacroInfo *MI = MD.getMacroInfo()) {
2599+
if (!MI->isUsed() && MI->isWarnIfUnused())
2600+
Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
2601+
2602+
if (MI->isWarnIfUnused())
2603+
WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
2604+
2605+
Undef = AllocateUndefMacroDirective(MacroNameTok.getLocation());
2606+
}
25952607

25962608
// If the callbacks want to know, tell them about the macro #undef.
25972609
// Note: no matter if the macro was defined or not.
25982610
if (Callbacks)
2599-
Callbacks->MacroUndefined(MacroNameTok, MD);
2600-
2601-
// If the macro is not defined, this is a noop undef, just return.
2602-
const MacroInfo *MI = MD.getMacroInfo();
2603-
if (!MI)
2604-
return;
2605-
2606-
if (!MI->isUsed() && MI->isWarnIfUnused())
2607-
Diag(MI->getDefinitionLoc(), diag::pp_macro_not_used);
2608-
2609-
if (MI->isWarnIfUnused())
2610-
WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
2611+
Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
26112612

2612-
appendMacroDirective(MacroNameTok.getIdentifierInfo(),
2613-
AllocateUndefMacroDirective(MacroNameTok.getLocation()));
2613+
if (Undef)
2614+
appendMacroDirective(II, Undef);
26142615
}
26152616

26162617
//===----------------------------------------------------------------------===//

‎clang/lib/Lex/PreprocessingRecord.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,8 @@ void PreprocessingRecord::MacroDefined(const Token &Id,
422422
}
423423

424424
void PreprocessingRecord::MacroUndefined(const Token &Id,
425-
const MacroDefinition &MD) {
425+
const MacroDefinition &MD,
426+
const MacroDirective *Undef) {
426427
MD.forAllDefinitions([&](MacroInfo *MI) { MacroDefinitions.erase(MI); });
427428
}
428429

‎clang/tools/libclang/Indexing.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ class IndexPPCallbacks : public PPCallbacks {
262262
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
263263
/// MI is released immediately following this callback.
264264
void MacroUndefined(const Token &MacroNameTok,
265-
const MacroDefinition &MD) override {}
265+
const MacroDefinition &MD,
266+
const MacroDirective *UD) override {}
266267

267268
/// MacroExpands - This is called by when a macro invocation is found.
268269
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,

‎clang/unittests/Basic/SourceManagerTest.cpp

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,18 @@ TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
249249
namespace {
250250

251251
struct MacroAction {
252+
enum Kind { kExpansion, kDefinition, kUnDefinition};
253+
252254
SourceLocation Loc;
253255
std::string Name;
254-
bool isDefinition; // if false, it is expansion.
255-
256-
MacroAction(SourceLocation Loc, StringRef Name, bool isDefinition)
257-
: Loc(Loc), Name(Name), isDefinition(isDefinition) { }
256+
unsigned MAKind : 3;
257+
258+
MacroAction(SourceLocation Loc, StringRef Name, unsigned K)
259+
: Loc(Loc), Name(Name), MAKind(K) { }
260+
261+
bool isExpansion() const { return MAKind == kExpansion; }
262+
bool isDefinition() const { return MAKind & kDefinition; }
263+
bool isUnDefinition() const { return MAKind & kUnDefinition; }
258264
};
259265

260266
class MacroTracker : public PPCallbacks {
@@ -267,21 +273,33 @@ class MacroTracker : public PPCallbacks {
267273
const MacroDirective *MD) override {
268274
Macros.push_back(MacroAction(MD->getLocation(),
269275
MacroNameTok.getIdentifierInfo()->getName(),
270-
true));
276+
MacroAction::kDefinition));
277+
}
278+
void MacroUndefined(const Token &MacroNameTok,
279+
const MacroDefinition &MD,
280+
const MacroDirective *UD) override {
281+
Macros.push_back(
282+
MacroAction(UD ? UD->getLocation() : SourceLocation(),
283+
MacroNameTok.getIdentifierInfo()->getName(),
284+
UD ? MacroAction::kDefinition | MacroAction::kUnDefinition
285+
: MacroAction::kUnDefinition));
271286
}
272287
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
273288
SourceRange Range, const MacroArgs *Args) override {
274289
Macros.push_back(MacroAction(MacroNameTok.getLocation(),
275290
MacroNameTok.getIdentifierInfo()->getName(),
276-
false));
291+
MacroAction::kExpansion));
277292
}
278293
};
279294

280295
}
281296

282297
TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
283298
const char *header =
284-
"#define MACRO_IN_INCLUDE 0\n";
299+
"#define MACRO_IN_INCLUDE 0\n"
300+
"#define MACRO_DEFINED\n"
301+
"#undef MACRO_DEFINED\n"
302+
"#undef MACRO_UNDEFINED\n";
285303

286304
const char *main =
287305
"#define M(x) x\n"
@@ -327,42 +345,54 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
327345
// Make sure we got the tokens that we expected.
328346
ASSERT_EQ(0U, toks.size());
329347

330-
ASSERT_EQ(9U, Macros.size());
348+
ASSERT_EQ(15U, Macros.size());
331349
// #define M(x) x
332-
ASSERT_TRUE(Macros[0].isDefinition);
350+
ASSERT_TRUE(Macros[0].isDefinition());
333351
ASSERT_EQ("M", Macros[0].Name);
334352
// #define INC "/test-header.h"
335-
ASSERT_TRUE(Macros[1].isDefinition);
353+
ASSERT_TRUE(Macros[1].isDefinition());
336354
ASSERT_EQ("INC", Macros[1].Name);
337355
// M expansion in #include M(INC)
338-
ASSERT_FALSE(Macros[2].isDefinition);
356+
ASSERT_FALSE(Macros[2].isDefinition());
339357
ASSERT_EQ("M", Macros[2].Name);
340358
// INC expansion in #include M(INC)
341-
ASSERT_FALSE(Macros[3].isDefinition);
359+
ASSERT_TRUE(Macros[3].isExpansion());
342360
ASSERT_EQ("INC", Macros[3].Name);
343361
// #define MACRO_IN_INCLUDE 0
344-
ASSERT_TRUE(Macros[4].isDefinition);
362+
ASSERT_TRUE(Macros[4].isDefinition());
345363
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[4].Name);
364+
// #define MACRO_DEFINED
365+
ASSERT_TRUE(Macros[5].isDefinition());
366+
ASSERT_FALSE(Macros[5].isUnDefinition());
367+
ASSERT_EQ("MACRO_DEFINED", Macros[5].Name);
368+
// #undef MACRO_DEFINED
369+
ASSERT_TRUE(Macros[6].isDefinition());
370+
ASSERT_TRUE(Macros[6].isUnDefinition());
371+
ASSERT_EQ("MACRO_DEFINED", Macros[6].Name);
372+
// #undef MACRO_UNDEFINED
373+
ASSERT_FALSE(Macros[7].isDefinition());
374+
ASSERT_TRUE(Macros[7].isUnDefinition());
375+
ASSERT_EQ("MACRO_UNDEFINED", Macros[7].Name);
346376
// #define INC2 </test-header.h>
347-
ASSERT_TRUE(Macros[5].isDefinition);
348-
ASSERT_EQ("INC2", Macros[5].Name);
377+
ASSERT_TRUE(Macros[8].isDefinition());
378+
ASSERT_EQ("INC2", Macros[8].Name);
349379
// M expansion in #include M(INC2)
350-
ASSERT_FALSE(Macros[6].isDefinition);
351-
ASSERT_EQ("M", Macros[6].Name);
380+
ASSERT_FALSE(Macros[9].isDefinition());
381+
ASSERT_EQ("M", Macros[9].Name);
352382
// INC2 expansion in #include M(INC2)
353-
ASSERT_FALSE(Macros[7].isDefinition);
354-
ASSERT_EQ("INC2", Macros[7].Name);
383+
ASSERT_TRUE(Macros[10].isExpansion());
384+
ASSERT_EQ("INC2", Macros[10].Name);
355385
// #define MACRO_IN_INCLUDE 0
356-
ASSERT_TRUE(Macros[8].isDefinition);
357-
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[8].Name);
386+
ASSERT_TRUE(Macros[11].isDefinition());
387+
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[11].Name);
358388

359389
// The INC expansion in #include M(INC) comes before the first
360390
// MACRO_IN_INCLUDE definition of the included file.
361391
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[3].Loc, Macros[4].Loc));
362392

363393
// The INC2 expansion in #include M(INC2) comes before the second
364394
// MACRO_IN_INCLUDE definition of the included file.
365-
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[7].Loc, Macros[8].Loc));
395+
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
366396
}
367397

368398
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.