Skip to content

Commit 2927a6e

Browse files
authored
fix(preproc): Allow multiple definitions of the same macro
1 parent b1e0853 commit 2927a6e

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

src/cxx/preprocessor.cc

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,23 @@ struct Macro {
271271
const TokList *body = nullptr;
272272
bool objLike = true;
273273
bool variadic = false;
274+
275+
bool operator!=(const Macro &other) const { return !operator==(other); }
276+
277+
bool operator==(const Macro &other) const {
278+
if (formals != other.formals) return false;
279+
if (objLike != other.objLike) return false;
280+
if (variadic != other.variadic) return false;
281+
return isSame(body, other.body);
282+
}
283+
284+
bool isSame(const TokList *ls, const TokList *rs) const {
285+
if (ls == rs) return true;
286+
if (!ls || !rs) return false;
287+
if (ls->head->kind != rs->head->kind) return false;
288+
if (ls->head->text != rs->head->text) return false;
289+
return isSame(ls->tail, rs->tail);
290+
}
274291
};
275292

276293
struct SourceFile {
@@ -1379,10 +1396,7 @@ void Preprocessor::Private::defineMacro(const TokList *ts) {
13791396

13801397
auto name = ts->head->text;
13811398

1382-
if (auto it = macros_.find(name); it != macros_.end()) {
1383-
warning(ts->head->token(), fmt::format("'{}' macro redefined", name));
1384-
macros_.erase(it);
1385-
}
1399+
Macro m;
13861400

13871401
if (ts->tail && !ts->tail->head->space &&
13881402
ts->tail->head->is(TokenKind::T_LPAREN)) {
@@ -1407,18 +1421,23 @@ void Preprocessor::Private::defineMacro(const TokList *ts) {
14071421
expect(ts, TokenKind::T_RPAREN);
14081422
}
14091423

1410-
Macro m;
14111424
m.objLike = false;
14121425
m.body = ts;
14131426
m.formals = std::move(formals);
14141427
m.variadic = variadic;
1415-
macros_.emplace(name, std::move(m));
1416-
return;
1428+
} else {
1429+
m.objLike = true;
1430+
m.body = ts->tail;
1431+
}
1432+
1433+
if (auto it = macros_.find(name); it != macros_.end()) {
1434+
if (it->second != m) {
1435+
warning(ts->head->token(), fmt::format("'{}' macro redefined", name));
1436+
}
1437+
1438+
macros_.erase(it);
14171439
}
14181440

1419-
Macro m;
1420-
m.objLike = true;
1421-
m.body = ts->tail;
14221441
macros_.emplace(name, std::move(m));
14231442
}
14241443

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %cxx -verify -E %s -o - | %filecheck %s
2+
3+
#define WANTS_CC 1
4+
5+
#define WANTS_CC 1
6+
7+
static_assert(WANTS_CC == 1);
8+
9+
// CHECK: {{^}}static_assert(1 == 1);{{$}}
10+
11+
#define WANTS_CC 2 // expected-warning {{'WANTS_CC' macro redefined}}
12+
13+
static_assert(WANTS_CC == 2);
14+
15+
// CHECK: {{^}}static_assert(2 == 2);{{$}}

0 commit comments

Comments
 (0)