Skip to content

Commit 3cce7ae

Browse files
[clang][ExtractAPI] Fix quirks in interaction with submodules (llvm#105868) (#9193)
Extension SGFs require the module system to be enabled in order to discover which module defines the extended external type. This patch ensures the following: - Associate symbols with their top level module name, and that only top level modules are considered as modules for emitting extension SGFs. - Ensure we don't drop macro definitions that came from a submodule. To this end look at all defined macros in `PPCalbacks::EndOfMainFile` instead of relying on `PPCallbacks::MacroDefined` being called to detect a macro definition. rdar://123020565
1 parent 851b0c7 commit 3cce7ae

File tree

10 files changed

+425
-784
lines changed

10 files changed

+425
-784
lines changed

clang/include/clang/ExtractAPI/DeclarationFragments.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,9 @@ class DeclarationFragmentsBuilder {
411411
/// Build DeclarationFragments for a macro.
412412
///
413413
/// \param Name name of the macro.
414-
/// \param MD the associated MacroDirective.
414+
/// \param MI the associated MacroInfo.
415415
static DeclarationFragments getFragmentsForMacro(StringRef Name,
416-
const MacroDirective *MD);
416+
const MacroInfo *MI);
417417

418418
/// Build DeclarationFragments for a typedef \p TypedefNameDecl.
419419
static DeclarationFragments

clang/include/clang/ExtractAPI/ExtractAPIVisitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
213213

214214
StringRef getOwningModuleName(const Decl &D) {
215215
if (auto *OwningModule = D.getImportedOwningModule())
216-
return OwningModule->Name;
216+
return OwningModule->getTopLevelModule()->Name;
217217

218218
return {};
219219
}

clang/lib/ExtractAPI/DeclarationFragments.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,14 +1327,12 @@ DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
13271327

13281328
DeclarationFragments
13291329
DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
1330-
const MacroDirective *MD) {
1330+
const MacroInfo *MI) {
13311331
DeclarationFragments Fragments;
13321332
Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword)
13331333
.appendSpace();
13341334
Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier);
13351335

1336-
auto *MI = MD->getMacroInfo();
1337-
13381336
if (MI->isFunctionLike()) {
13391337
Fragments.append("(", DeclarationFragments::FragmentKind::Text);
13401338
unsigned numParameters = MI->getNumParams();

clang/lib/ExtractAPI/ExtractAPIConsumer.cpp

Lines changed: 36 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -286,78 +286,59 @@ class MacroCallback : public PPCallbacks {
286286
MacroCallback(const SourceManager &SM, APISet &API, Preprocessor &PP)
287287
: SM(SM), API(API), PP(PP) {}
288288

289-
void MacroDefined(const Token &MacroNameToken,
290-
const MacroDirective *MD) override {
291-
auto *MacroInfo = MD->getMacroInfo();
289+
void EndOfMainFile() override {
290+
for (const auto &M : PP.macros()) {
291+
auto *II = M.getFirst();
292+
auto MD = PP.getMacroDefinition(II);
293+
auto *MI = MD.getMacroInfo();
292294

293-
if (MacroInfo->isBuiltinMacro())
294-
return;
295+
if (!MI)
296+
continue;
295297

296-
auto SourceLoc = MacroNameToken.getLocation();
297-
if (SM.isWrittenInBuiltinFile(SourceLoc) ||
298-
SM.isWrittenInCommandLineFile(SourceLoc))
299-
return;
298+
// Ignore header guard macros
299+
if (MI->isUsedForHeaderGuard())
300+
continue;
300301

301-
PendingMacros.emplace_back(MacroNameToken, MD);
302-
}
302+
// Ignore builtin macros and ones defined via the command line.
303+
if (MI->isBuiltinMacro())
304+
continue;
303305

304-
// If a macro gets undefined at some point during preprocessing of the inputs
305-
// it means that it isn't an exposed API and we should therefore not add a
306-
// macro definition for it.
307-
void MacroUndefined(const Token &MacroNameToken, const MacroDefinition &MD,
308-
const MacroDirective *Undef) override {
309-
// If this macro wasn't previously defined we don't need to do anything
310-
// here.
311-
if (!Undef)
312-
return;
313-
314-
llvm::erase_if(PendingMacros, [&MD, this](const PendingMacro &PM) {
315-
return MD.getMacroInfo()->isIdenticalTo(*PM.MD->getMacroInfo(), PP,
316-
/*Syntactically*/ false);
317-
});
318-
}
306+
auto DefLoc = MI->getDefinitionLoc();
319307

320-
void EndOfMainFile() override {
321-
for (auto &PM : PendingMacros) {
322-
// `isUsedForHeaderGuard` is only set when the preprocessor leaves the
323-
// file so check for it here.
324-
if (PM.MD->getMacroInfo()->isUsedForHeaderGuard())
308+
if (SM.isWrittenInBuiltinFile(DefLoc) ||
309+
SM.isWrittenInCommandLineFile(DefLoc))
325310
continue;
326311

327-
if (!shouldMacroBeIncluded(PM))
312+
auto AssociatedModuleMacros = MD.getModuleMacros();
313+
StringRef OwningModuleName;
314+
if (!AssociatedModuleMacros.empty())
315+
OwningModuleName = AssociatedModuleMacros.back()
316+
->getOwningModule()
317+
->getTopLevelModuleName();
318+
319+
if (!shouldMacroBeIncluded(DefLoc, OwningModuleName))
328320
continue;
329321

330-
StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
331-
PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
322+
StringRef Name = II->getName();
323+
PresumedLoc Loc = SM.getPresumedLoc(DefLoc);
332324
SmallString<128> USR;
333-
index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM,
334-
USR);
335-
325+
index::generateUSRForMacro(Name, DefLoc, SM, USR);
336326
API.createRecord<extractapi::MacroDefinitionRecord>(
337327
USR, Name, SymbolReference(), Loc,
338-
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
328+
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, MI),
339329
DeclarationFragmentsBuilder::getSubHeadingForMacro(Name),
340-
SM.isInSystemHeader(PM.MacroNameToken.getLocation()));
330+
SM.isInSystemHeader(DefLoc));
341331
}
342-
343-
PendingMacros.clear();
344332
}
345333

346-
protected:
347-
struct PendingMacro {
348-
Token MacroNameToken;
349-
const MacroDirective *MD;
350-
351-
PendingMacro(const Token &MacroNameToken, const MacroDirective *MD)
352-
: MacroNameToken(MacroNameToken), MD(MD) {}
353-
};
354-
355-
virtual bool shouldMacroBeIncluded(const PendingMacro &PM) { return true; }
334+
virtual bool shouldMacroBeIncluded(const SourceLocation &MacroLoc,
335+
StringRef ModuleName) {
336+
return true;
337+
}
356338

357339
const SourceManager &SM;
358340
APISet &API;
359341
Preprocessor &PP;
360-
llvm::SmallVector<PendingMacro> PendingMacros;
361342
};
362343

363344
class APIMacroCallback : public MacroCallback {
@@ -366,9 +347,10 @@ class APIMacroCallback : public MacroCallback {
366347
LocationFileChecker &LCF)
367348
: MacroCallback(SM, API, PP), LCF(LCF) {}
368349

369-
bool shouldMacroBeIncluded(const PendingMacro &PM) override {
350+
bool shouldMacroBeIncluded(const SourceLocation &MacroLoc,
351+
StringRef ModuleName) override {
370352
// Do not include macros from external files
371-
return LCF(PM.MacroNameToken.getLocation());
353+
return LCF(MacroLoc) || API.ProductName == ModuleName;
372354
}
373355

374356
private:

clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,8 +928,8 @@ bool SymbolGraphSerializer::traverseObjCCategoryRecord(
928928
return true;
929929

930930
auto *CurrentModule = ModuleForCurrentSymbol;
931-
if (Record->isExtendingExternalModule())
932-
ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source];
931+
if (auto ModuleExtendedByRecord = Record->getExtendedExternalModule())
932+
ModuleForCurrentSymbol = &ExtendedModules[*ModuleExtendedByRecord];
933933

934934
if (!walkUpFromObjCCategoryRecord(Record))
935935
return false;

clang/test/ExtractAPI/bool.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// RUN: split-file %s %t
33
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
44
// RUN: %t/reference.output.json.in >> %t/reference.output.json
5-
// RUN: %clang -extract-api --pretty-sgf -target arm64-apple-macosx \
6-
// RUN: %t/input.h -o %t/output.json
5+
// RUN: %clang_cc1 -extract-api --product-name=BoolTest --pretty-sgf -triple arm64-apple-macosx \
6+
// RUN: %t/input.h -o %t/output.json
77

88
// Generator version is not consistent across test runs, normalize it.
99
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
@@ -15,7 +15,7 @@
1515
bool Foo;
1616

1717
bool IsFoo(bool Bar);
18-
/// expected-no-diagnostics
18+
// expected-no-diagnostics
1919

2020
//--- reference.output.json.in
2121
{
@@ -28,7 +28,7 @@ bool IsFoo(bool Bar);
2828
"generator": "?"
2929
},
3030
"module": {
31-
"name": "",
31+
"name": "BoolTest",
3232
"platform": {
3333
"architecture": "arm64",
3434
"operatingSystem": {

0 commit comments

Comments
 (0)