summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Lex/MacroInfo.cpp2
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp10
-rw-r--r--clang/lib/Serialization/ASTReader.cpp333
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp2
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp138
5 files changed, 344 insertions, 141 deletions
diff --git a/clang/lib/Lex/MacroInfo.cpp b/clang/lib/Lex/MacroInfo.cpp
index a7b55156c5d..0325a80c3be 100644
--- a/clang/lib/Lex/MacroInfo.cpp
+++ b/clang/lib/Lex/MacroInfo.cpp
@@ -144,7 +144,7 @@ MacroDirective::DefInfo MacroDirective::getDefinition() {
isPublic = VisMD->isPublic();
}
- return DefInfo();
+ return DefInfo(0, UndefLoc, !isPublic.hasValue() || isPublic.getValue());
}
const MacroDirective::DefInfo
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 721760afa0e..84f1ea5b1fa 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -293,11 +293,11 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
for (MacroDirective::DefInfo PrevDef = Def.getPreviousDefinition();
PrevDef && !PrevDef.isUndefined();
PrevDef = PrevDef.getPreviousDefinition()) {
- if (PrevDef.getDirective()->isAmbiguous()) {
- Diag(PrevDef.getMacroInfo()->getDefinitionLoc(),
- diag::note_pp_ambiguous_macro_other)
- << Identifier.getIdentifierInfo();
- }
+ Diag(PrevDef.getMacroInfo()->getDefinitionLoc(),
+ diag::note_pp_ambiguous_macro_other)
+ << Identifier.getIdentifierInfo();
+ if (!PrevDef.getDirective()->isAmbiguous())
+ break;
}
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f93a52d7fdf..c0da65d583b 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -579,11 +579,34 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
}
if (F.Kind == MK_Module) {
+ // Macro definitions are stored from newest to oldest, so reverse them
+ // before registering them.
+ llvm::SmallVector<unsigned, 8> MacroSizes;
for (SmallVectorImpl<uint32_t>::iterator
- I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; ++I) {
- MacroID MacID = Reader.getGlobalMacroID(F, *I);
- Reader.addPendingMacroFromModule(II, &F, MacID, F.DirectImportLoc);
+ I = LocalMacroIDs.begin(), E = LocalMacroIDs.end(); I != E; /**/) {
+ unsigned Size = 1;
+
+ static const uint32_t HasOverridesFlag = 0x80000000U;
+ if (I + 1 != E && (I[1] & HasOverridesFlag))
+ Size += 1 + (I[1] & ~HasOverridesFlag);
+
+ MacroSizes.push_back(Size);
+ I += Size;
}
+
+ SmallVectorImpl<uint32_t>::iterator I = LocalMacroIDs.end();
+ for (SmallVectorImpl<unsigned>::reverse_iterator SI = MacroSizes.rbegin(),
+ SE = MacroSizes.rend();
+ SI != SE; ++SI) {
+ I -= *SI;
+
+ uint32_t LocalMacroID = *I;
+ llvm::ArrayRef<uint32_t> Overrides;
+ if (*SI != 1)
+ Overrides = llvm::makeArrayRef(&I[2], *SI - 2);
+ Reader.addPendingMacroFromModule(II, &F, LocalMacroID, Overrides);
+ }
+ assert(I == LocalMacroIDs.begin());
} else {
Reader.addPendingMacroFromPCH(II, &F, MacroDirectivesOffset);
}
@@ -1323,12 +1346,19 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
return HFI;
}
-void ASTReader::addPendingMacroFromModule(IdentifierInfo *II,
- ModuleFile *M,
- GlobalMacroID GMacID,
- SourceLocation ImportLoc) {
+void
+ASTReader::addPendingMacroFromModule(IdentifierInfo *II, ModuleFile *M,
+ GlobalMacroID GMacID,
+ llvm::ArrayRef<SubmoduleID> Overrides) {
assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
- PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, ImportLoc));
+ SubmoduleID *OverrideData = 0;
+ if (!Overrides.empty()) {
+ OverrideData = new (Context) SubmoduleID[Overrides.size() + 1];
+ OverrideData[0] = Overrides.size();
+ for (unsigned I = 0; I != Overrides.size(); ++I)
+ OverrideData[I + 1] = getGlobalSubmoduleID(*M, Overrides[I]);
+ }
+ PendingMacroIDs[II].push_back(PendingMacroInfo(M, GMacID, OverrideData));
}
void ASTReader::addPendingMacroFromPCH(IdentifierInfo *II,
@@ -1477,6 +1507,59 @@ void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
IdentifierGeneration[II] = CurrentGeneration;
}
+struct ASTReader::ModuleMacroInfo {
+ SubmoduleID SubModID;
+ MacroInfo *MI;
+ SubmoduleID *Overrides;
+ // FIXME: Remove this.
+ ModuleFile *F;
+
+ bool isDefine() const { return MI; }
+
+ SubmoduleID getSubmoduleID() const { return SubModID; }
+
+ llvm::ArrayRef<SubmoduleID> getOverriddenSubmodules() const {
+ if (!Overrides)
+ return llvm::ArrayRef<SubmoduleID>();
+ return llvm::makeArrayRef(Overrides + 1, *Overrides);
+ }
+
+ DefMacroDirective *import(Preprocessor &PP, SourceLocation ImportLoc) const {
+ if (!MI)
+ return 0;
+ return PP.AllocateDefMacroDirective(MI, ImportLoc, /*isImported=*/true);
+ }
+};
+
+ASTReader::ModuleMacroInfo *
+ASTReader::getModuleMacro(const PendingMacroInfo &PMInfo) {
+ ModuleMacroInfo Info;
+
+ uint32_t ID = PMInfo.ModuleMacroData.MacID;
+ if (ID & 1) {
+ // Macro undefinition.
+ Info.SubModID = getGlobalSubmoduleID(*PMInfo.M, ID >> 1);
+ Info.MI = 0;
+ } else {
+ // Macro definition.
+ GlobalMacroID GMacID = getGlobalMacroID(*PMInfo.M, ID >> 1);
+ assert(GMacID);
+
+ // If this macro has already been loaded, don't do so again.
+ // FIXME: This is highly dubious. Multiple macro definitions can have the
+ // same MacroInfo (and hence the same GMacID) due to #pragma push_macro etc.
+ if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
+ return 0;
+
+ Info.MI = getMacro(GMacID);
+ Info.SubModID = Info.MI->getOwningModuleID();
+ }
+ Info.Overrides = PMInfo.ModuleMacroData.Overrides;
+ Info.F = PMInfo.M;
+
+ return new (Context) ModuleMacroInfo(Info);
+}
+
void ASTReader::resolvePendingMacro(IdentifierInfo *II,
const PendingMacroInfo &PMInfo) {
assert(II);
@@ -1486,42 +1569,21 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II,
PMInfo.PCHMacroData.MacroDirectivesOffset);
return;
}
-
- // Module Macro.
- GlobalMacroID GMacID = PMInfo.ModuleMacroData.GMacID;
- SourceLocation ImportLoc =
- SourceLocation::getFromRawEncoding(PMInfo.ModuleMacroData.ImportLoc);
+ // Module Macro.
- assert(GMacID);
- // If this macro has already been loaded, don't do so again.
- if (MacrosLoaded[GMacID - NUM_PREDEF_MACRO_IDS])
+ ModuleMacroInfo *MMI = getModuleMacro(PMInfo);
+ if (!MMI)
return;
- MacroInfo *MI = getMacro(GMacID);
- SubmoduleID SubModID = MI->getOwningModuleID();
- MacroDirective *MD = PP.AllocateDefMacroDirective(MI, ImportLoc,
- /*isImported=*/true);
-
- // Determine whether this macro definition is visible.
- bool Hidden = false;
- Module *Owner = 0;
- if (SubModID) {
- if ((Owner = getSubmodule(SubModID))) {
- if (Owner->NameVisibility == Module::Hidden) {
- // The owning module is not visible, and this macro definition
- // should not be, either.
- Hidden = true;
-
- // Note that this macro definition was hidden because its owning
- // module is not yet visible.
- HiddenNamesMap[Owner].push_back(HiddenName(II, MD));
- }
- }
+ Module *Owner = getSubmodule(MMI->getSubmoduleID());
+ if (Owner && Owner->NameVisibility == Module::Hidden) {
+ // Macros in the owning module are hidden. Just remember this macro to
+ // install if we make this module visible.
+ HiddenNamesMap[Owner].HiddenMacros.insert(std::make_pair(II, MMI));
+ } else {
+ installImportedMacro(II, MMI, Owner);
}
-
- if (!Hidden)
- installImportedMacro(II, MD, Owner);
}
void ASTReader::installPCHMacroDirectives(IdentifierInfo *II,
@@ -1606,31 +1668,138 @@ static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI,
return PrevInSystem && NewInSystem;
}
-void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD,
- Module *Owner) {
- assert(II && MD);
+void ASTReader::removeOverriddenMacros(IdentifierInfo *II,
+ AmbiguousMacros &Ambig,
+ llvm::ArrayRef<SubmoduleID> Overrides) {
+ for (unsigned OI = 0, ON = Overrides.size(); OI != ON; ++OI) {
+ SubmoduleID OwnerID = Overrides[OI];
- DefMacroDirective *DefMD = cast<DefMacroDirective>(MD);
+ // If this macro is not yet visible, remove it from the hidden names list.
+ Module *Owner = getSubmodule(OwnerID);
+ HiddenNames &Hidden = HiddenNamesMap[Owner];
+ HiddenMacrosMap::iterator HI = Hidden.HiddenMacros.find(II);
+ if (HI != Hidden.HiddenMacros.end()) {
+ removeOverriddenMacros(II, Ambig, HI->second->getOverriddenSubmodules());
+ Hidden.HiddenMacros.erase(HI);
+ }
+
+ // If this macro is already in our list of conflicts, remove it from there.
+ for (unsigned AI = 0, AN = Ambig.size(); AI != AN; ++AI)
+ if (Ambig[AI]->getInfo()->getOwningModuleID() == OwnerID)
+ Ambig.erase(Ambig.begin() + AI);
+ }
+}
+
+ASTReader::AmbiguousMacros *
+ASTReader::removeOverriddenMacros(IdentifierInfo *II,
+ llvm::ArrayRef<SubmoduleID> Overrides) {
MacroDirective *Prev = PP.getMacroDirective(II);
- if (Prev) {
- MacroDirective::DefInfo PrevDef = Prev->getDefinition();
- MacroInfo *PrevMI = PrevDef.getMacroInfo();
- MacroInfo *NewMI = DefMD->getInfo();
- if (NewMI != PrevMI && !PrevMI->isIdenticalTo(*NewMI, PP,
- /*Syntactically=*/true)) {
- // Before marking the macros as ambiguous, check if this is a case where
- // both macros are in system headers. If so, we trust that the system
- // did not get it wrong. This also handles cases where Clang's own
- // headers have a different spelling of certain system macros:
- // #define LONG_MAX __LONG_MAX__ (clang's limits.h)
- // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h)
- if (!areDefinedInSystemModules(PrevMI, NewMI, Owner, *this)) {
- PrevDef.getDirective()->setAmbiguous(true);
- DefMD->setAmbiguous(true);
- }
+ if (!Prev && Overrides.empty())
+ return 0;
+
+ DefMacroDirective *PrevDef = Prev ? Prev->getDefinition().getDirective() : 0;
+ if (PrevDef && PrevDef->isAmbiguous()) {
+ // We had a prior ambiguity. Check whether we resolve it (or make it worse).
+ AmbiguousMacros &Ambig = AmbiguousMacroDefs[II];
+ Ambig.push_back(PrevDef);
+
+ removeOverriddenMacros(II, Ambig, Overrides);
+
+ if (!Ambig.empty())
+ return &Ambig;
+
+ AmbiguousMacroDefs.erase(II);
+ } else {
+ // There's no ambiguity yet. Maybe we're introducing one.
+ llvm::SmallVector<DefMacroDirective*, 1> Ambig;
+ if (PrevDef)
+ Ambig.push_back(PrevDef);
+
+ removeOverriddenMacros(II, Ambig, Overrides);
+
+ if (!Ambig.empty()) {
+ AmbiguousMacros &Result = AmbiguousMacroDefs[II];
+ Result.swap(Ambig);
+ return &Result;
}
}
-
+
+ // We ended up with no ambiguity.
+ return 0;
+}
+
+void ASTReader::installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
+ Module *Owner) {
+ assert(II && Owner);
+
+ SourceLocation ImportLoc = Owner->MacroVisibilityLoc;
+ if (ImportLoc.isInvalid()) {
+ // FIXME: If we made macros from this module visible but didn't provide a
+ // source location for the import, we don't have a location for the macro.
+ // Use the location at which the containing module file was first imported
+ // for now.
+ ImportLoc = MMI->F->DirectImportLoc;
+ }
+
+ llvm::SmallVectorImpl<DefMacroDirective*> *Prev =
+ removeOverriddenMacros(II, MMI->getOverriddenSubmodules());
+
+
+ // Create a synthetic macro definition corresponding to the import (or null
+ // if this was an undefinition of the macro).
+ DefMacroDirective *MD = MMI->import(PP, ImportLoc);
+
+ // If there's no ambiguity, just install the macro.
+ if (!Prev) {
+ if (MD)
+ PP.appendMacroDirective(II, MD);
+ else
+ PP.appendMacroDirective(II, PP.AllocateUndefMacroDirective(ImportLoc));
+ return;
+ }
+ assert(!Prev->empty());
+
+ if (!MD) {
+ // We imported a #undef that didn't remove all prior definitions. The most
+ // recent prior definition remains, and we install it in the place of the
+ // imported directive.
+ MacroInfo *NewMI = Prev->back()->getInfo();
+ Prev->pop_back();
+ MD = PP.AllocateDefMacroDirective(NewMI, ImportLoc, /*Imported*/true);
+ }
+
+ // We're introducing a macro definition that creates or adds to an ambiguity.
+ // We can resolve that ambiguity if this macro is token-for-token identical to
+ // all of the existing definitions.
+ MacroInfo *NewMI = MD->getInfo();
+ assert(NewMI && "macro definition with no MacroInfo?");
+ while (!Prev->empty()) {
+ MacroInfo *PrevMI = Prev->back()->getInfo();
+ assert(PrevMI && "macro definition with no MacroInfo?");
+
+ // Before marking the macros as ambiguous, check if this is a case where
+ // both macros are in system headers. If so, we trust that the system
+ // did not get it wrong. This also handles cases where Clang's own
+ // headers have a different spelling of certain system macros:
+ // #define LONG_MAX __LONG_MAX__ (clang's limits.h)
+ // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h)
+ //
+ // FIXME: Remove the defined-in-system-headers check. clang's limits.h
+ // overrides the system limits.h's macros, so there's no conflict here.
+ if (NewMI != PrevMI &&
+ !PrevMI->isIdenticalTo(*NewMI, PP, /*Syntactically=*/true) &&
+ !areDefinedInSystemModules(PrevMI, NewMI, Owner, *this))
+ break;
+
+ // The previous definition is the same as this one (or both are defined in
+ // system modules so we can assume they're equivalent); we don't need to
+ // track it any more.
+ Prev->pop_back();
+ }
+
+ if (!Prev->empty())
+ MD->setAmbiguous(true);
+
PP.appendMacroDirective(II, MD);
}
@@ -2828,30 +2997,25 @@ static void moveMethodToBackOfGlobalList(Sema &S, ObjCMethodDecl *Method) {
}
void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) {
- for (unsigned I = 0, N = Names.size(); I != N; ++I) {
- switch (Names[I].getKind()) {
- case HiddenName::Declaration: {
- Decl *D = Names[I].getDecl();
- bool wasHidden = D->Hidden;
- D->Hidden = false;
-
- if (wasHidden && SemaObj) {
- if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) {
- moveMethodToBackOfGlobalList(*SemaObj, Method);
- }
+ for (unsigned I = 0, N = Names.HiddenDecls.size(); I != N; ++I) {
+ Decl *D = Names.HiddenDecls[I];
+ bool wasHidden = D->Hidden;
+ D->Hidden = false;
+
+ if (wasHidden && SemaObj) {
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) {
+ moveMethodToBackOfGlobalList(*SemaObj, Method);
}
- break;
- }
- case HiddenName::MacroVisibility: {
- std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro();
- installImportedMacro(Macro.first, Macro.second, Owner);
- break;
- }
}
}
+
+ for (HiddenMacrosMap::const_iterator I = Names.HiddenMacros.begin(),
+ E = Names.HiddenMacros.end();
+ I != E; ++I)
+ installImportedMacro(I->first, I->second, Owner);
}
-void ASTReader::makeModuleVisible(Module *Mod,
+void ASTReader::makeModuleVisible(Module *Mod,
Module::NameVisibilityKind NameVisibility,
SourceLocation ImportLoc,
bool Complain) {
@@ -2866,15 +3030,18 @@ void ASTReader::makeModuleVisible(Module *Mod,
// there is nothing more to do.
continue;
}
-
+
if (!Mod->isAvailable()) {
// Modules that aren't available cannot be made visible.
continue;
}
// Update the module's name visibility.
+ if (NameVisibility >= Module::MacrosVisible &&
+ Mod->NameVisibility < Module::MacrosVisible)
+ Mod->MacroVisibilityLoc = ImportLoc;
Mod->NameVisibility = NameVisibility;
-
+
// If we've already deserialized any names from this module,
// mark them as visible.
HiddenNamesMapType::iterator Hidden = HiddenNamesMap.find(Mod);
@@ -7457,14 +7624,14 @@ void ASTReader::finishPendingActions() {
SmallVector<PendingMacroInfo, 2> GlobalIDs;
GlobalIDs.swap(PendingMacroIDs.begin()[I].second);
// Initialize the macro history from chained-PCHs ahead of module imports.
- for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
+ for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
if (Info.M->Kind != MK_Module)
resolvePendingMacro(II, Info);
}
// Handle module imports.
- for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
+ for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
if (Info.M->Kind == MK_Module)
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 18dbb053b99..958e18183c0 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -412,7 +412,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
// Note that this declaration was hidden because its owning module is
// not yet visible.
- Reader.HiddenNamesMap[Owner].push_back(D);
+ Reader.HiddenNamesMap[Owner].HiddenDecls.push_back(D);
}
}
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 11b57407c29..df73af43050 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -2962,80 +2962,91 @@ class ASTIdentifierTableTrait {
return false;
}
- DefMacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD,
- SubmoduleID &ModID) {
+ typedef llvm::SmallVectorImpl<SubmoduleID> OverriddenList;
+
+ MacroDirective *
+ getFirstPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID) {
ModID = 0;
- if (DefMacroDirective *DefMD = getPublicSubmoduleMacro(MD, ModID))
- if (!shouldIgnoreMacro(DefMD, IsModule, PP))
- return DefMD;
+ llvm::SmallVector<SubmoduleID, 1> Overridden;
+ if (MacroDirective *NextMD = getPublicSubmoduleMacro(MD, ModID, Overridden))
+ if (!shouldIgnoreMacro(NextMD, IsModule, PP))
+ return NextMD;
return 0;
}
- DefMacroDirective *getNextPublicSubmoduleMacro(DefMacroDirective *MD,
- SubmoduleID &ModID) {
- if (DefMacroDirective *
- DefMD = getPublicSubmoduleMacro(MD->getPrevious(), ModID))
- if (!shouldIgnoreMacro(DefMD, IsModule, PP))
- return DefMD;
+ MacroDirective *
+ getNextPublicSubmoduleMacro(MacroDirective *MD, SubmoduleID &ModID,
+ OverriddenList &Overridden) {
+ if (MacroDirective *NextMD =
+ getPublicSubmoduleMacro(MD->getPrevious(), ModID, Overridden))
+ if (!shouldIgnoreMacro(NextMD, IsModule, PP))
+ return NextMD;
return 0;
}
/// \brief Traverses the macro directives history and returns the latest
- /// macro that is public and not undefined in the same submodule.
- /// A macro that is defined in submodule A and undefined in submodule B,
+ /// public macro definition or undefinition that is not in ModID.
+ /// A macro that is defined in submodule A and undefined in submodule B
/// will still be considered as defined/exported from submodule A.
- DefMacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
- SubmoduleID &ModID) {
+ /// ModID is updated to the module containing the returned directive.
+ ///
+ /// FIXME: This process breaks down if a module defines a macro, imports
+ /// another submodule that changes the macro, then changes the
+ /// macro again itself.
+ MacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
+ SubmoduleID &ModID,
+ OverriddenList &Overridden) {
if (!MD)
return 0;
+ Overridden.clear();
SubmoduleID OrigModID = ModID;
- bool isUndefined = false;
- Optional<bool> isPublic;
+ Optional<bool> IsPublic;
for (; MD; MD = MD->getPrevious()) {
SubmoduleID ThisModID = getSubmoduleID(MD);
if (ThisModID == 0) {
- isUndefined = false;
- isPublic = Optional<bool>();
+ IsPublic = Optional<bool>();
continue;
}
- if (ThisModID != ModID){
+ if (ThisModID != ModID) {
ModID = ThisModID;
- isUndefined = false;
- isPublic = Optional<bool>();
+ IsPublic = Optional<bool>();
}
+
+ // If this is a definition from a submodule import, that submodule's
+ // definition is overridden by the definition or undefinition that we
+ // started with.
+ // FIXME: This should only apply to macros defined in OrigModID.
+ // We can't do that currently, because a #include of a different submodule
+ // of the same module just leaks through macros instead of providing new
+ // DefMacroDirectives for them.
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
+ if (SubmoduleID SourceID = DefMD->getInfo()->getOwningModuleID())
+ Overridden.push_back(SourceID);
+
// We are looking for a definition in a different submodule than the one
// that we started with. If a submodule has re-definitions of the same
// macro, only the last definition will be used as the "exported" one.
if (ModID == OrigModID)
continue;
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- if (!isUndefined && (!isPublic.hasValue() || isPublic.getValue()))
- return DefMD;
- continue;
+ // The latest visibility directive for a name in a submodule affects all
+ // the directives that come before it.
+ if (VisibilityMacroDirective *VisMD =
+ dyn_cast<VisibilityMacroDirective>(MD)) {
+ if (!IsPublic.hasValue())
+ IsPublic = VisMD->isPublic();
+ } else if (!IsPublic.hasValue() || IsPublic.getValue()) {
+ // FIXME: If we find an imported macro, we should include its list of
+ // overrides in our export.
+ return MD;
}
-
- if (isa<UndefMacroDirective>(MD)) {
- isUndefined = true;
- continue;
- }
-
- VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
- if (!isPublic.hasValue())
- isPublic = VisMD->isPublic();
}
return 0;
}
SubmoduleID getSubmoduleID(MacroDirective *MD) {
- if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
- MacroInfo *MI = DefMD->getInfo();
- if (unsigned ID = MI->getOwningModuleID())
- return ID;
- return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc());
- }
return Writer.inferSubmoduleIDFromLocation(MD->getLocation());
}
@@ -3066,11 +3077,18 @@ public:
DataLen += 4; // MacroDirectives offset.
if (IsModule) {
SubmoduleID ModID;
- for (DefMacroDirective *
- DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
- DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
- DataLen += 4; // MacroInfo ID.
+ llvm::SmallVector<SubmoduleID, 4> Overridden;
+ for (MacroDirective *
+ MD = getFirstPublicSubmoduleMacro(Macro, ModID);
+ MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) {
+ // Previous macro's overrides.
+ if (!Overridden.empty())
+ DataLen += 4 * (1 + Overridden.size());
+ DataLen += 4; // MacroInfo ID or ModuleID.
}
+ // Previous macro's overrides.
+ if (!Overridden.empty())
+ DataLen += 4 * (1 + Overridden.size());
DataLen += 4;
}
}
@@ -3096,6 +3114,15 @@ public:
Out.write(II->getNameStart(), KeyLen);
}
+ static void emitMacroOverrides(raw_ostream &Out,
+ llvm::ArrayRef<SubmoduleID> Overridden) {
+ if (!Overridden.empty()) {
+ clang::io::Emit32(Out, Overridden.size() | 0x80000000U);
+ for (unsigned I = 0, N = Overridden.size(); I != N; ++I)
+ clang::io::Emit32(Out, Overridden[I]);
+ }
+ }
+
void EmitData(raw_ostream& Out, IdentifierInfo* II,
IdentID ID, unsigned) {
MacroDirective *Macro = 0;
@@ -3123,13 +3150,22 @@ public:
if (IsModule) {
// Write the IDs of macros coming from different submodules.
SubmoduleID ModID;
- for (DefMacroDirective *
- DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
- DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
- MacroID InfoID = Writer.getMacroID(DefMD->getInfo());
- assert(InfoID);
- clang::io::Emit32(Out, InfoID);
+ llvm::SmallVector<SubmoduleID, 4> Overridden;
+ for (MacroDirective *
+ MD = getFirstPublicSubmoduleMacro(Macro, ModID);
+ MD; MD = getNextPublicSubmoduleMacro(MD, ModID, Overridden)) {
+ MacroID InfoID = 0;
+ emitMacroOverrides(Out, Overridden);
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+ InfoID = Writer.getMacroID(DefMD->getInfo());
+ assert(InfoID);
+ clang::io::Emit32(Out, InfoID << 1);
+ } else {
+ assert(isa<UndefMacroDirective>(MD));
+ clang::io::Emit32(Out, (ModID << 1) | 1);
+ }
}
+ emitMacroOverrides(Out, Overridden);
clang::io::Emit32(Out, 0);
}
}
OpenPOWER on IntegriCloud