Skip to content

Commit 4c6d972

Browse files
committed
Clang importer: collapse redefined macros.
In C, macros can be redefined so long as the redefinitions are tokenwise equivalent. Provide the Clang importer with the same ability by determining when tokenwise equivalent macros would be imported as different Swift declarations, and collapse them into a single declaration.
1 parent 4f69bfc commit 4c6d972

File tree

6 files changed

+51
-7
lines changed

6 files changed

+51
-7
lines changed

lib/ClangImporter/ImportMacro.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,25 @@ ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
393393
if (!macro)
394394
return nullptr;
395395

396-
// Look for the value for an already-imported macro.
397-
auto known = ImportedMacros.find(macro);
396+
// Look for macros imported with the same name.
397+
auto known = ImportedMacros.find(name);
398398
if (known != ImportedMacros.end()) {
399-
return known->second;
399+
// Check whether this macro has already been imported.
400+
for (const auto &entry : known->second) {
401+
if (entry.first == macro) return entry.second;
402+
}
403+
404+
// Otherwise, check whether this macro is identical to a macro that has
405+
// already been imported.
406+
auto &clangPP = getClangPreprocessor();
407+
for (const auto &entry : known->second) {
408+
// If the macro is equal to an existing macro, map down to the same
409+
// declaration.
410+
if (macro->isIdenticalTo(*entry.first, clangPP, true)) {
411+
known->second.push_back({macro, entry.second});
412+
return entry.second;
413+
}
414+
}
400415
}
401416

402417
ImportingEntityRAII ImportingEntity(*this);
@@ -408,6 +423,6 @@ ValueDecl *ClangImporter::Implementation::importMacro(Identifier name,
408423
return nullptr;
409424

410425
auto valueDecl = ::importMacro(*this, DC, name, macro, macro);
411-
ImportedMacros[macro] = valueDecl;
426+
ImportedMacros[name].push_back({macro, valueDecl});
412427
return valueDecl;
413428
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,16 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
402402
llvm::DenseMap<std::pair<ClangDeclAndFlag, DeclContext *>, Decl *>
403403
ImportedProtocolDecls;
404404

405-
/// \brief Mapping of already-imported macros.
406-
llvm::DenseMap<clang::MacroInfo *, ValueDecl *> ImportedMacros;
405+
/// Mapping from identifiers to the set of macros that have that name along
406+
/// with their corresponding Swift declaration.
407+
///
408+
/// Multiple macro definitions can map to the same declaration if the
409+
/// macros are identically defined.
410+
llvm::DenseMap<Identifier,
411+
SmallVector<std::pair<clang::MacroInfo *, ValueDecl *>, 2>>
412+
ImportedMacros;
407413

408-
/// Keeps track of active selector-basde lookups, so that we don't infinitely
414+
/// Keeps track of active selector-based lookups, so that we don't infinitely
409415
/// recurse when checking whether a method with a given selector has already
410416
/// been imported.
411417
llvm::DenseMap<std::pair<ObjCSelector, char>, unsigned>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define REDEF_1 "hello"
2+
#define REDEF_2 "world"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define REDEF_1 "hello"
2+
#define REDEF_2 "Swift"

test/ClangModules/Inputs/custom-modules/module.map

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,11 @@ module Requires {
128128
module SwiftName {
129129
header "SwiftName.h"
130130
}
131+
132+
module MacrosRedefA {
133+
header "MacrosRedefA.h"
134+
}
135+
136+
module MacrosRedefB {
137+
header "MacrosRedefB.h"
138+
}

test/ClangModules/macros_redef.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/custom-modules -parse -verify %s
2+
3+
import MacrosRedefA
4+
import MacrosRedefB
5+
6+
func testMacroRedef() {
7+
var s: String
8+
s = REDEF_1
9+
s = REDEF_2 // expected-error{{ambiguous use of 'REDEF_2'}}
10+
}
11+

0 commit comments

Comments
 (0)