forked from OSchip/llvm-project
Track which particular submodule #undef's a macro, so that the actual
#undef only occurs if that submodule is imported. llvm-svn: 165773
This commit is contained in:
parent
98b4164503
commit
cfa46a82b8
|
@ -395,7 +395,10 @@ private:
|
|||
/// global macro ID to produce a local ID.
|
||||
GlobalMacroMapType GlobalMacroMap;
|
||||
|
||||
typedef llvm::DenseMap<serialization::MacroID, MacroUpdate> MacroUpdatesMap;
|
||||
typedef llvm::DenseMap<serialization::MacroID,
|
||||
llvm::SmallVector<std::pair<serialization::SubmoduleID,
|
||||
MacroUpdate>, 1> >
|
||||
MacroUpdatesMap;
|
||||
|
||||
/// \brief Mapping from (global) macro IDs to the set of updates to be
|
||||
/// performed to the corresponding macro.
|
||||
|
@ -417,30 +420,50 @@ private:
|
|||
|
||||
/// \brief An entity that has been hidden.
|
||||
class HiddenName {
|
||||
/// \brief The hidden declaration or macro.
|
||||
llvm::PointerUnion<Decl *, MacroInfo *> DeclOrMacro;
|
||||
public:
|
||||
enum NameKind {
|
||||
Declaration,
|
||||
MacroVisibility,
|
||||
MacroUndef
|
||||
} Kind;
|
||||
|
||||
/// \brief The name being defined to a macro, for the macro case.
|
||||
IdentifierInfo *Identifier;
|
||||
private:
|
||||
unsigned Loc;
|
||||
|
||||
union {
|
||||
Decl *D;
|
||||
MacroInfo *MI;
|
||||
};
|
||||
|
||||
IdentifierInfo *Id;
|
||||
|
||||
public:
|
||||
HiddenName(Decl *D) : DeclOrMacro(D), Identifier() { }
|
||||
HiddenName(IdentifierInfo *II, MacroInfo *MI)
|
||||
: DeclOrMacro(MI), Identifier(II) { }
|
||||
HiddenName(Decl *D) : Kind(Declaration), Loc(), D(D), Id() { }
|
||||
|
||||
bool isDecl() const { return DeclOrMacro.is<Decl*>(); }
|
||||
bool isMacro() const { return !isDecl(); }
|
||||
HiddenName(IdentifierInfo *II, MacroInfo *MI)
|
||||
: Kind(MacroVisibility), Loc(), MI(MI), Id(II) { }
|
||||
|
||||
HiddenName(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc)
|
||||
: Kind(MacroUndef), Loc(Loc.getRawEncoding()), MI(MI), Id(II) { }
|
||||
|
||||
NameKind getKind() const { return Kind; }
|
||||
|
||||
Decl *getDecl() const {
|
||||
assert(isDecl() && "Hidden name is not a declaration");
|
||||
return DeclOrMacro.get<Decl *>();
|
||||
assert(getKind() == Declaration && "Hidden name is not a declaration");
|
||||
return D;
|
||||
}
|
||||
|
||||
std::pair<IdentifierInfo *, MacroInfo *> getMacro() const {
|
||||
assert(isMacro() && "Hidden name is not a macro!");
|
||||
return std::make_pair(Identifier, DeclOrMacro.get<MacroInfo *>());
|
||||
assert((getKind() == MacroUndef || getKind() == MacroVisibility)
|
||||
&& "Hidden name is not a macro!");
|
||||
return std::make_pair(Id, MI);
|
||||
}
|
||||
};
|
||||
|
||||
SourceLocation getMacroUndefLoc() const {
|
||||
assert(getKind() == MacroUndef && "Hidden name is not an undef!");
|
||||
return SourceLocation::getFromRawEncoding(Loc);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A set of hidden declarations.
|
||||
typedef llvm::SmallVector<HiddenName, 2>
|
||||
|
|
|
@ -87,11 +87,13 @@ void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI,
|
|||
}
|
||||
|
||||
// Find the end of the definition chain.
|
||||
MacroInfo *Prev = StoredMI;
|
||||
MacroInfo *PrevPrev;
|
||||
MacroInfo *Prev;
|
||||
MacroInfo *PrevPrev = StoredMI;
|
||||
bool Ambiguous = StoredMI->isAmbiguous();
|
||||
bool MatchedOther = false;
|
||||
do {
|
||||
Prev = PrevPrev;
|
||||
|
||||
// If the macros are not identical, we have an ambiguity.
|
||||
if (!Prev->isIdenticalTo(*MI, *this)) {
|
||||
if (!Ambiguous) {
|
||||
|
@ -125,25 +127,29 @@ void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI,
|
|||
void Preprocessor::makeLoadedMacroInfoVisible(IdentifierInfo *II,
|
||||
MacroInfo *MI) {
|
||||
assert(MI->isFromAST() && "Macro must be from the AST");
|
||||
assert(MI->isDefined() && "Macro is not visible");
|
||||
|
||||
MacroInfo *&StoredMI = Macros[II];
|
||||
if (StoredMI == MI) {
|
||||
// Easy case: this is the first macro anyway.
|
||||
II->setHasMacroDefinition(true);
|
||||
II->setHasMacroDefinition(MI->isDefined());
|
||||
return;
|
||||
}
|
||||
|
||||
// Go find the macro and pull it out of the list.
|
||||
// FIXME: Yes, this is O(N), and making a pile of macros visible would be
|
||||
// quadratic.
|
||||
// FIXME: Yes, this is O(N), and making a pile of macros visible or hidden
|
||||
// would be quadratic, but it's extremely rare.
|
||||
MacroInfo *Prev = StoredMI;
|
||||
while (Prev->getPreviousDefinition() != MI)
|
||||
Prev = Prev->getPreviousDefinition();
|
||||
Prev->setPreviousDefinition(MI->getPreviousDefinition());
|
||||
MI->setPreviousDefinition(0);
|
||||
|
||||
// Add the macro back to the list.
|
||||
addLoadedMacroInfo(II, MI);
|
||||
|
||||
II->setHasMacroDefinition(StoredMI->isDefined());
|
||||
if (II->isFromAST())
|
||||
II->setChangedSinceDeserialization();
|
||||
}
|
||||
|
||||
/// \brief Undefine a macro for this identifier.
|
||||
|
|
|
@ -1364,9 +1364,28 @@ void ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset,
|
|||
MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
|
||||
if (Update != MacroUpdates.end()) {
|
||||
if (MI->getUndefLoc().isInvalid()) {
|
||||
MI->setUndefLoc(Update->second.UndefLoc);
|
||||
if (PPMutationListener *Listener = PP.getPPMutationListener())
|
||||
Listener->UndefinedMacro(MI);
|
||||
for (unsigned I = 0, N = Update->second.size(); I != N; ++I) {
|
||||
bool Hidden = false;
|
||||
if (unsigned SubmoduleID = Update->second[I].first) {
|
||||
if (Module *Owner = getSubmodule(SubmoduleID)) {
|
||||
if (Owner->NameVisibility == Module::Hidden) {
|
||||
// Note that this #undef is hidden.
|
||||
Hidden = true;
|
||||
|
||||
// Record this hiding for later.
|
||||
HiddenNamesMap[Owner].push_back(
|
||||
HiddenName(II, MI, Update->second[I].second.UndefLoc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Hidden) {
|
||||
MI->setUndefLoc(Update->second[I].second.UndefLoc);
|
||||
if (PPMutationListener *Listener = PP.getPPMutationListener())
|
||||
Listener->UndefinedMacro(MI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
MacroUpdates.erase(Update);
|
||||
}
|
||||
|
@ -2517,7 +2536,11 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
|
|||
if (I == N)
|
||||
break;
|
||||
|
||||
MacroUpdates[ID].UndefLoc = ReadSourceLocation(F, Record, I);
|
||||
SourceLocation UndefLoc = ReadSourceLocation(F, Record, I);
|
||||
SubmoduleID SubmoduleID = getGlobalSubmoduleID(F, Record[I++]);;
|
||||
MacroUpdate Update;
|
||||
Update.UndefLoc = UndefLoc;
|
||||
MacroUpdates[ID].push_back(std::make_pair(SubmoduleID, Update));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2619,15 +2642,30 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries(ModuleFile &M) {
|
|||
|
||||
void ASTReader::makeNamesVisible(const HiddenNames &Names) {
|
||||
for (unsigned I = 0, N = Names.size(); I != N; ++I) {
|
||||
if (Names[I].isDecl()) {
|
||||
switch (Names[I].getKind()) {
|
||||
case HiddenName::Declaration:
|
||||
Names[I].getDecl()->Hidden = false;
|
||||
continue;
|
||||
break;
|
||||
|
||||
case HiddenName::MacroVisibility: {
|
||||
std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
|
||||
Macro.second->setHidden(!Macro.second->isPublic());
|
||||
if (Macro.second->isDefined()) {
|
||||
PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
|
||||
Macro.second->setHidden(!Macro.second->isPublic());
|
||||
if (Macro.second->isDefined()) {
|
||||
PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
|
||||
case HiddenName::MacroUndef: {
|
||||
std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
|
||||
if (Macro.second->isDefined()) {
|
||||
Macro.second->setUndefLoc(Names[I].getMacroUndefLoc());
|
||||
if (PPMutationListener *Listener = PP.getPPMutationListener())
|
||||
Listener->UndefinedMacro(Macro.second);
|
||||
PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3686,6 +3686,7 @@ void ASTWriter::WriteMacroUpdates() {
|
|||
I != E; ++I) {
|
||||
addMacroRef(I->first, Record);
|
||||
AddSourceLocation(I->second.UndefLoc, Record);
|
||||
Record.push_back(inferSubmoduleIDFromLocation(I->second.UndefLoc));
|
||||
}
|
||||
Stream.EmitRecord(MACRO_UPDATES, Record);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "macros_top.h"
|
||||
@__experimental_modules_import macros_top;
|
||||
#define LEFT unsigned long
|
||||
|
||||
#undef TOP_LEFT_UNDEF
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "macros_top.h"
|
||||
@__experimental_modules_import macros_top;
|
||||
#define RIGHT unsigned short
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
#undef TOP_RIGHT_UNDEF
|
|
@ -11,3 +11,6 @@
|
|||
|
||||
|
||||
#define TOP_RIGHT_REDEF int
|
||||
|
||||
#define TOP_RIGHT_UNDEF int
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ module macros_left {
|
|||
module macros_right {
|
||||
header "macros_right.h"
|
||||
export *
|
||||
explicit module undef {
|
||||
header "macros_right_undef.h"
|
||||
}
|
||||
}
|
||||
module macros { header "macros.h" }
|
||||
module category_top { header "category_top.h" }
|
||||
|
|
|
@ -107,10 +107,6 @@ void test1() {
|
|||
# error TOP should be visible
|
||||
#endif
|
||||
|
||||
#ifndef TOP_LEFT_UNDEF
|
||||
# error TOP_LEFT_UNDEF should be visible
|
||||
#endif
|
||||
|
||||
void test2() {
|
||||
int i;
|
||||
float f;
|
||||
|
@ -129,3 +125,13 @@ void test3() {
|
|||
double d;
|
||||
LEFT_RIGHT_DIFFERENT *dp = &d; // okay
|
||||
}
|
||||
|
||||
#ifndef TOP_RIGHT_UNDEF
|
||||
# error TOP_RIGHT_UNDEF should still be defined
|
||||
#endif
|
||||
|
||||
@__experimental_modules_import macros_right.undef;
|
||||
|
||||
#ifdef TOP_RIGHT_UNDEF
|
||||
# error TOP_RIGHT_UNDEF should not be defined
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue