r202560 - If a module A exports a macro M, and a module B imports that macro and #undef's
Richard Smith
richard at metafoo.co.uk
Thu Mar 20 15:40:24 PDT 2014
On Thu, Mar 20, 2014 at 3:20 PM, Ben Langmuir <blangmuir at apple.com> wrote:
> Hi Richard,
>
> I''m seeing an assertion failure that I think is caused by this commit. A
> macro that is undef'd in a module imported by a pch seems to get an invalid
> location, which then triggers an assertion in UndefMacroDirective's
> constructor. The details, as well as a test case, are at
> http://llvm.org/PR19215. Could you take a look?
>
Thanks for the heads-up, investigating...
> Thanks,
>
> Ben
>
> > Author: rsmith
> > Date: Fri Feb 28 18:08:04 2014
> > New Revision: 202560
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=202560&view=rev
> > Log:
> > If a module A exports a macro M, and a module B imports that macro and
> #undef's
> > it, importers of B should not see the macro. This is complicated by the
> fact
> > that A's macro could also be visible through a different path. The rules
> (as
> > hashed out on cfe-commits) are included as a documentation update in this
> > change.
> >
> > With this, the number of regressions in libc++'s testsuite when modules
> are
> > enabled drops from 47 to 7. Those remaining 7 are also macro-related,
> and are
> > due to remaining bugs in this change (in particular, the handling of
> submodules
> > is imperfect).
> >
> > Added:
> > cfe/trunk/test/Modules/macros2.c
> > cfe/trunk/test/PCH/macro-undef.cpp
> > Modified:
> > cfe/trunk/docs/Modules.rst
> > cfe/trunk/include/clang/Basic/Module.h
> > cfe/trunk/include/clang/Serialization/ASTReader.h
> > cfe/trunk/include/clang/Serialization/Module.h
> > cfe/trunk/lib/Lex/MacroInfo.cpp
> > cfe/trunk/lib/Lex/PPMacroExpansion.cpp
> > cfe/trunk/lib/Serialization/ASTReader.cpp
> > cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> > cfe/trunk/lib/Serialization/ASTWriter.cpp
> > cfe/trunk/test/Modules/Inputs/macros_other.h
> > cfe/trunk/test/Modules/Inputs/macros_right.h
> > cfe/trunk/test/Modules/Inputs/macros_right_undef.h
> > cfe/trunk/test/Modules/Inputs/macros_top.h
> > cfe/trunk/test/Modules/Inputs/module.map
> > cfe/trunk/test/Modules/macros.c
> >
> > Modified: cfe/trunk/docs/Modules.rst
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/Modules.rst?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/docs/Modules.rst (original)
> > +++ cfe/trunk/docs/Modules.rst Fri Feb 28 18:08:04 2014
> > @@ -198,6 +198,40 @@ Command-line parameters
> > ``-fmodule-map-file=<file>``
> > Load the given module map file if a header from its directory or one
> of its subdirectories is loaded.
> >
> > +Module Semantics
> > +================
> > +
> > +Modules are modeled as if each submodule were a separate translation
> unit, and a module import makes names from the other translation unit
> visible. Each submodule starts with a new preprocessor state and an empty
> translation unit.
> > +
> > +.. note::
> > +
> > + This behavior is currently only approximated when building a module.
> Entities within a submodule that has already been built are visible when
> building later submodules in that module. This can lead to fragile modules
> that depend on the build order used for the submodules of the module, and
> should not be relied upon.
> > +
> > +As an example, in C, this implies that if two structs are defined in
> different submodules with the same name, those two types are distinct types
> (but may be *compatible* types if their definitions match. In C++, two
> structs defined with the same name in different submodules are the *same*
> type, and must be equivalent under C++'s One Definition Rule.
> > +
> > +.. note::
> > +
> > + Clang currently only performs minimal checking for violations of the
> One Definition Rule.
> > +
> > +Macros
> > +------
> > +
> > +The C and C++ preprocessor assumes that the input text is a single
> linear buffer, but with modules this is not the case. It is possible to
> import two modules that have conflicting definitions for a macro (or where
> one ``#define``\s a macro and the other ``#undef``\ines it). The rules for
> handling macro definitions in the presence of modules are as follows:
> > +
> > +* Each definition and undefinition of a macro is considered to be a
> distinct entity.
> > +* Such entities are *visible* if they are from the current submodule or
> translation unit, or if they were exported from a submodule that has been
> imported.
> > +* A ``#define X`` or ``#undef X`` directive *overrides* all definitions
> of ``X`` that are visible at the point of the directive.
> > +* A ``#define`` or ``#undef`` directive is *active* if it is visible
> and no visible directive overrides it.
> > +* A set of macro directives is *consistent* if it consists of only
> ``#undef`` directives, or if all ``#define`` directives in the set define
> the macro name to the same sequence of tokens (following the usual rules
> for macro redefinitions).
> > +* If a macro name is used and the set of active directives is not
> consistent, the program is ill-formed. Otherwise, the (unique) meaning of
> the macro name is used.
> > +
> > +For example, suppose:
> > +
> > +* ``<stdio.h>`` defines a macro ``getc`` (and exports its ``#define``)
> > +* ``<cstdio>`` imports the ``<stdio.h>`` module and undefines the macro
> (and exports its ``#undef``)
> > +
> > +The ``#undef`` overrides the ``#define``, and a source file that
> imports both modules *in any order* will not see ``getc`` defined as a
> macro.
> > +
> > Module Map Language
> > ===================
> >
> >
> > Modified: cfe/trunk/include/clang/Basic/Module.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/Module.h (original)
> > +++ cfe/trunk/include/clang/Basic/Module.h Fri Feb 28 18:08:04 2014
> > @@ -160,11 +160,14 @@ public:
> > MacrosVisible,
> > /// \brief All of the names in this module are visible.
> > AllVisible
> > - };
> > -
> > - ///\ brief The visibility of names within this particular module.
> > + };
> > +
> > + /// \brief The visibility of names within this particular module.
> > NameVisibilityKind NameVisibility;
> >
> > + /// \brief The location at which macros within this module became
> visible.
> > + SourceLocation MacroVisibilityLoc;
> > +
> > /// \brief The location of the inferred submodule.
> > SourceLocation InferredSubmoduleLoc;
> >
> >
> > Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
> > +++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri Feb 28
> 18:08:04 2014
> > @@ -64,6 +64,7 @@ class ASTUnit; // FIXME: Layering violat
> > class Attr;
> > class Decl;
> > class DeclContext;
> > +class DefMacroDirective;
> > class DiagnosticOptions;
> > class NestedNameSpecifier;
> > class CXXBaseSpecifier;
> > @@ -471,18 +472,22 @@ private:
> > /// global submodule ID to produce a local ID.
> > GlobalSubmoduleMapType GlobalSubmoduleMap;
> >
> > + /// \brief Information on a macro definition or undefinition that is
> visible
> > + /// at the end of a submodule.
> > + struct ModuleMacroInfo;
> > +
> > /// \brief An entity that has been hidden.
> > class HiddenName {
> > public:
> > enum NameKind {
> > Declaration,
> > - MacroVisibility
> > + Macro
> > } Kind;
> >
> > private:
> > union {
> > Decl *D;
> > - MacroDirective *MD;
> > + ModuleMacroInfo *MMI;
> > };
> >
> > IdentifierInfo *Id;
> > @@ -490,8 +495,8 @@ private:
> > public:
> > HiddenName(Decl *D) : Kind(Declaration), D(D), Id() { }
> >
> > - HiddenName(IdentifierInfo *II, MacroDirective *MD)
> > - : Kind(MacroVisibility), MD(MD), Id(II) { }
> > + HiddenName(IdentifierInfo *II, ModuleMacroInfo *MMI)
> > + : Kind(Macro), MMI(MMI), Id(II) { }
> >
> > NameKind getKind() const { return Kind; }
> >
> > @@ -500,15 +505,21 @@ private:
> > return D;
> > }
> >
> > - std::pair<IdentifierInfo *, MacroDirective *> getMacro() const {
> > - assert(getKind() == MacroVisibility && "Hidden name is not a
> macro!");
> > - return std::make_pair(Id, MD);
> > + std::pair<IdentifierInfo *, ModuleMacroInfo *> getMacro() const {
> > + assert(getKind() == Macro && "Hidden name is not a macro!");
> > + return std::make_pair(Id, MMI);
> > }
> > };
> >
> > + typedef llvm::SmallDenseMap<IdentifierInfo*,
> > + ModuleMacroInfo*> HiddenMacrosMap;
> > +
> > /// \brief A set of hidden declarations.
> > - typedef SmallVector<HiddenName, 2> HiddenNames;
> > -
> > + struct HiddenNames {
> > + SmallVector<Decl*, 2> HiddenDecls;
> > + HiddenMacrosMap HiddenMacros;
> > + };
> > +
> > typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType;
> >
> > /// \brief A mapping from each of the hidden submodules to the
> deserialized
> > @@ -564,8 +575,8 @@ private:
> > ModuleFile *M;
> >
> > struct ModuleMacroDataTy {
> > - serialization::GlobalMacroID GMacID;
> > - unsigned ImportLoc;
> > + uint32_t MacID;
> > + serialization::SubmoduleID *Overrides;
> > };
> > struct PCHMacroDataTy {
> > uint64_t MacroDirectivesOffset;
> > @@ -577,10 +588,10 @@ private:
> > };
> >
> > PendingMacroInfo(ModuleFile *M,
> > - serialization::GlobalMacroID GMacID,
> > - SourceLocation ImportLoc) : M(M) {
> > - ModuleMacroData.GMacID = GMacID;
> > - ModuleMacroData.ImportLoc = ImportLoc.getRawEncoding();
> > + uint32_t MacID,
> > + serialization::SubmoduleID *Overrides) : M(M) {
> > + ModuleMacroData.MacID = MacID;
> > + ModuleMacroData.Overrides = Overrides;
> > }
> >
> > PendingMacroInfo(ModuleFile *M, uint64_t MacroDirectivesOffset) :
> M(M) {
> > @@ -1253,14 +1264,14 @@ public:
> > /// \param ImportLoc The location at which the import occurs.
> > ///
> > /// \param Complain Whether to complain about conflicting module
> imports.
> > - void makeModuleVisible(Module *Mod,
> > + void makeModuleVisible(Module *Mod,
> > Module::NameVisibilityKind NameVisibility,
> > SourceLocation ImportLoc,
> > bool Complain);
> > -
> > +
> > /// \brief Make the names within this set of hidden names visible.
> > void makeNamesVisible(const HiddenNames &Names, Module *Owner);
> > -
> > +
> > /// \brief Set the AST callbacks listener.
> > void setListener(ASTReaderListener *listener) {
> > Listener.reset(listener);
> > @@ -1687,14 +1698,27 @@ public:
> > serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M,
> > unsigned LocalID);
> >
> > + ModuleMacroInfo *getModuleMacro(const PendingMacroInfo &PMInfo);
> > +
> > void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo
> &PMInfo);
> >
> > void installPCHMacroDirectives(IdentifierInfo *II,
> > ModuleFile &M, uint64_t Offset);
> >
> > - void installImportedMacro(IdentifierInfo *II, MacroDirective *MD,
> > + void installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
> > Module *Owner);
> >
> > + typedef llvm::SmallVector<DefMacroDirective*, 1> AmbiguousMacros;
> > + llvm::DenseMap<IdentifierInfo*, AmbiguousMacros> AmbiguousMacroDefs;
> > +
> > + void
> > + removeOverriddenMacros(IdentifierInfo *II, AmbiguousMacros &Ambig,
> > + llvm::ArrayRef<serialization::SubmoduleID>
> Overrides);
> > +
> > + AmbiguousMacros *
> > + removeOverriddenMacros(IdentifierInfo *II,
> > + llvm::ArrayRef<serialization::SubmoduleID>
> Overrides);
> > +
> > /// \brief Retrieve the macro with the given ID.
> > MacroInfo *getMacro(serialization::MacroID ID);
> >
> > @@ -1875,7 +1899,7 @@ public:
> > void addPendingMacroFromModule(IdentifierInfo *II,
> > ModuleFile *M,
> > serialization::GlobalMacroID GMacID,
> > - SourceLocation ImportLoc);
> > +
> llvm::ArrayRef<serialization::SubmoduleID>);
> >
> > /// \brief Add a macro to deserialize its macro directive history from
> a PCH.
> > ///
> >
> > Modified: cfe/trunk/include/clang/Serialization/Module.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/Module.h?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Serialization/Module.h (original)
> > +++ cfe/trunk/include/clang/Serialization/Module.h Fri Feb 28 18:08:04
> 2014
> > @@ -171,6 +171,9 @@ public:
> > /// If module A depends on and imports module B, both modules will
> have the
> > /// same DirectImportLoc, but different ImportLoc (B's ImportLoc will
> be a
> > /// source location inside module A).
> > + ///
> > + /// WARNING: This is largely useless. It doesn't tell you when a
> module was
> > + /// made visible, just when the first submodule of that module was
> imported.
> > SourceLocation DirectImportLoc;
> >
> > /// \brief The source location where this module was first imported.
> >
> > Modified: cfe/trunk/lib/Lex/MacroInfo.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/MacroInfo.cpp?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Lex/MacroInfo.cpp (original)
> > +++ cfe/trunk/lib/Lex/MacroInfo.cpp Fri Feb 28 18:08:04 2014
> > @@ -144,7 +144,7 @@ MacroDirective::DefInfo MacroDirective::
> > isPublic = VisMD->isPublic();
> > }
> >
> > - return DefInfo();
> > + return DefInfo(0, UndefLoc, !isPublic.hasValue() ||
> isPublic.getValue());
> > }
> >
> > const MacroDirective::DefInfo
> >
> > Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
> > +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Fri Feb 28 18:08:04 2014
> > @@ -293,11 +293,11 @@ bool Preprocessor::HandleMacroExpandedId
> > 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;
> > }
> > }
> >
> >
> > Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Feb 28 18:08:04 2014
> > @@ -579,11 +579,34 @@ IdentifierInfo *ASTIdentifierLookupTrait
> > }
> >
> > 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_k
> > 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(I
> > 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(Iden
> > PMInfo.PCHMacroData.MacroDirectivesOffset);
> > return;
> > }
> > -
> > +
> > // Module Macro.
> >
> > - GlobalMacroID GMacID = PMInfo.ModuleMacroData.GMacID;
> > - SourceLocation ImportLoc =
> > -
> SourceLocation::getFromRawEncoding(PMInfo.ModuleMacroData.ImportLoc);
> > -
> > - 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(Ma
> > 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];
> > +
> > + // 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);
> > + }
> > +}
> >
> > - DefMacroDirective *DefMD = cast<DefMacroDirective>(MD);
> > +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
> > }
> >
> > 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
> > // 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)
> >
> > Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Feb 28 18:08:04
> 2014
> > @@ -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);
> > }
> > }
> > }
> >
> > Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Feb 28 18:08:04 2014
> > @@ -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;
> > - }
> > -
> > - if (isa<UndefMacroDirective>(MD)) {
> > - isUndefined = true;
> > - 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;
> > }
> > -
> > - 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);
> > }
> > }
> >
> > Modified: cfe/trunk/test/Modules/Inputs/macros_other.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/macros_other.h?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Modules/Inputs/macros_other.h (original)
> > +++ cfe/trunk/test/Modules/Inputs/macros_other.h Fri Feb 28 18:08:04 2014
> > @@ -1 +1,6 @@
> > -#define OTHER_INTEGER int
> > +#undef TOP_OTHER_UNDEF1
> > +#define TOP_OTHER_UNDEF2 42
> > +#define TOP_OTHER_REDEF1 1
> > +#define TOP_OTHER_REDEF1 3
> > +
> > +#define TOP_OTHER_DEF_RIGHT_UNDEF 4
> >
> > Modified: cfe/trunk/test/Modules/Inputs/macros_right.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/macros_right.h?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Modules/Inputs/macros_right.h (original)
> > +++ cfe/trunk/test/Modules/Inputs/macros_right.h Fri Feb 28 18:08:04 2014
> > @@ -17,3 +17,5 @@
> > #define TOP_RIGHT_REDEF float
> >
> > #define FN_ADD(x, y) (x+y)
> > +
> > +#undef TOP_OTHER_DEF_RIGHT_UNDEF
> >
> > Modified: cfe/trunk/test/Modules/Inputs/macros_right_undef.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/macros_right_undef.h?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Modules/Inputs/macros_right_undef.h (original)
> > +++ cfe/trunk/test/Modules/Inputs/macros_right_undef.h Fri Feb 28
> 18:08:04 2014
> > @@ -1 +1,4 @@
> > #undef TOP_RIGHT_UNDEF
> > +
> > + at import macros_top;
> > +#undef TOP_OTHER_DEF_RIGHT_UNDEF
> >
> > Modified: cfe/trunk/test/Modules/Inputs/macros_top.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/macros_top.h?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Modules/Inputs/macros_top.h (original)
> > +++ cfe/trunk/test/Modules/Inputs/macros_top.h Fri Feb 28 18:08:04 2014
> > @@ -14,3 +14,9 @@
> >
> > #define TOP_RIGHT_UNDEF int
> >
> > +#define TOP_OTHER_UNDEF1 42
> > +#undef TOP_OTHER_UNDEF2
> > +#define TOP_OTHER_REDEF1 1
> > +#define TOP_OTHER_REDEF2 2
> > +
> > +#define TOP_OTHER_DEF_RIGHT_UNDEF void
> >
> > Modified: cfe/trunk/test/Modules/Inputs/module.map
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Modules/Inputs/module.map (original)
> > +++ cfe/trunk/test/Modules/Inputs/module.map Fri Feb 28 18:08:04 2014
> > @@ -33,6 +33,7 @@ module macros_right {
> > }
> > }
> > module macros { header "macros.h" }
> > +module macros_other { header "macros_other.h" }
> > module category_top { header "category_top.h" }
> > module category_left {
> > header "category_left.h"
> >
> > Modified: cfe/trunk/test/Modules/macros.c
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/macros.c?rev=202560&r1=202559&r2=202560&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/Modules/macros.c (original)
> > +++ cfe/trunk/test/Modules/macros.c Fri Feb 28 18:08:04 2014
> > @@ -11,10 +11,8 @@
> > // FIXME: expected-note at Inputs/macros_left.h:11{{previous definition is
> here}}
> > // FIXME: expected-note at Inputs/macros_right.h:12{{previous definition
> is here}}
> > // expected-note at Inputs/macros_right.h:12{{expanding this definition of
> 'LEFT_RIGHT_DIFFERENT'}}
> > -// expected-note at Inputs/macros_top.h:13{{other definition of
> 'TOP_RIGHT_REDEF'}}
> > // expected-note at Inputs/macros_right.h:13{{expanding this definition of
> 'LEFT_RIGHT_DIFFERENT2'}}
> > // expected-note at Inputs/macros_left.h:14{{other definition of
> 'LEFT_RIGHT_DIFFERENT'}}
> > -// expected-note at Inputs/macros_right.h:17{{expanding this definition
> of 'TOP_RIGHT_REDEF'}}
> >
> > @import macros;
> >
> > @@ -79,8 +77,8 @@ void f() {
> > # error TOP should be visible
> > #endif
> >
> > -#ifndef TOP_LEFT_UNDEF
> > -# error TOP_LEFT_UNDEF should still be defined
> > +#ifdef TOP_LEFT_UNDEF
> > +# error TOP_LEFT_UNDEF should not be defined
> > #endif
> >
> > void test1() {
> > @@ -112,7 +110,7 @@ void test2() {
> > int i;
> > float f;
> > double d;
> > - TOP_RIGHT_REDEF *fp = &f; // expected-warning{{ambiguous expansion of
> macro 'TOP_RIGHT_REDEF'}}
> > + TOP_RIGHT_REDEF *fp = &f; // ok, right's definition overrides top's
> definition
> >
> > LEFT_RIGHT_IDENTICAL *ip = &i;
> > LEFT_RIGHT_DIFFERENT *ip2 = &i; // expected-warning{{ambiguous
> expansion of macro 'LEFT_RIGHT_DIFFERENT'}}
> > @@ -134,6 +132,33 @@ void test3() {
> >
> > @import macros_right.undef;
> >
> > -#ifndef TOP_RIGHT_UNDEF
> > -# error TOP_RIGHT_UNDEF should still be defined
> > +// FIXME: When macros_right.undef is built, macros_top is visible
> because
> > +// the state from building macros_right leaks through, so
> macros_right.undef
> > +// undefines macros_top's macro.
> > +#ifdef TOP_RIGHT_UNDEF
> > +# error TOP_RIGHT_UNDEF should not be defined
> > +#endif
> > +
> > + at import macros_other;
> > +
> > +#ifndef TOP_OTHER_UNDEF1
> > +# error TOP_OTHER_UNDEF1 should still be defined
> > +#endif
> > +
> > +#ifndef TOP_OTHER_UNDEF2
> > +# error TOP_OTHER_UNDEF2 should still be defined
> > #endif
> > +
> > +#ifndef TOP_OTHER_REDEF1
> > +# error TOP_OTHER_REDEF1 should still be defined
> > +#endif
> > +int n1 = TOP_OTHER_REDEF1; // expected-warning{{ambiguous expansion of
> macro 'TOP_OTHER_REDEF1'}}
> > +// expected-note at macros_top.h:19 {{expanding this definition}}
> > +// expected-note at macros_other.h:4 {{other definition}}
> > +
> > +#ifndef TOP_OTHER_REDEF2
> > +# error TOP_OTHER_REDEF2 should still be defined
> > +#endif
> > +int n2 = TOP_OTHER_REDEF2; // ok
> > +
> > +int n3 = TOP_OTHER_DEF_RIGHT_UNDEF; // ok
> >
> > Added: cfe/trunk/test/Modules/macros2.c
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/macros2.c?rev=202560&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/test/Modules/macros2.c (added)
> > +++ cfe/trunk/test/Modules/macros2.c Fri Feb 28 18:08:04 2014
> > @@ -0,0 +1,77 @@
> > +// RUN: rm -rf %t
> > +// RUN: %clang_cc1 -fmodules -x objective-c -emit-module
> -fmodules-cache-path=%t -fmodule-name=macros_top %S/Inputs/module.map
> > +// RUN: %clang_cc1 -fmodules -x objective-c -emit-module
> -fmodules-cache-path=%t -fmodule-name=macros_left %S/Inputs/module.map
> > +// RUN: %clang_cc1 -fmodules -x objective-c -emit-module
> -fmodules-cache-path=%t -fmodule-name=macros_right %S/Inputs/module.map
> > +// RUN: %clang_cc1 -fmodules -x objective-c -emit-module
> -fmodules-cache-path=%t -fmodule-name=macros %S/Inputs/module.map
> > +// RUN: %clang_cc1 -fmodules -x objective-c -verify
> -fmodules-cache-path=%t -I %S/Inputs %s
> > +
> > +// This test checks some of the same things as macros.c, but imports
> modules in
> > +// a different order.
> > +
> > + at import macros_other;
> > +
> > +int n0 = TOP_OTHER_DEF_RIGHT_UNDEF; // ok
> > +
> > + at import macros_top;
> > +
> > +TOP_OTHER_DEF_RIGHT_UNDEF *n0b; // expected-warning{{ambiguous
> expansion of macro 'TOP_OTHER_DEF_RIGHT_UNDEF'}}
> > +// expected-note at macros_top.h:22 {{expanding this definition of
> 'TOP_OTHER_DEF_RIGHT_UNDEF'}}
> > +// expected-note at macros_other.h:6 {{other definition of
> 'TOP_OTHER_DEF_RIGHT_UNDEF'}}
> > +
> > + at import macros_right;
> > + at import macros_left;
> > +
> > +#ifdef TOP_LEFT_UNDEF
> > +# error TOP_LEFT_UNDEF should not be defined
> > +#endif
> > +
> > +#ifndef TOP_RIGHT_UNDEF
> > +# error TOP_RIGHT_UNDEF should still be defined
> > +#endif
> > +
> > +void test() {
> > + float f;
> > + TOP_RIGHT_REDEF *fp = &f; // ok, right's definition overrides top's
> definition
> > +
> > + // Note, left's definition wins here, whereas right's definition wins
> in
> > + // macros.c.
> > + int i;
> > + LEFT_RIGHT_IDENTICAL *ip = &i;
> > + LEFT_RIGHT_DIFFERENT *ip2 = &f; // expected-warning{{ambiguous
> expansion of macro 'LEFT_RIGHT_DIFFERENT'}}
> > + // expected-note at macros_left.h:14 {{expanding this}}
> > + // expected-note at macros_right.h:12 {{other}}
> > + LEFT_RIGHT_DIFFERENT2 *ip3 = &f; // expected-warning{{ambiguous
> expansion of macro 'LEFT_RIGHT_DIFFERENT2}}
> > + // expected-note at macros_left.h:11 {{expanding this}}
> > + // expected-note at macros_right.h:13 {{other}}
> > +#undef LEFT_RIGHT_DIFFERENT3
> > + int LEFT_RIGHT_DIFFERENT3;
> > +}
> > +
> > + at import macros_right.undef;
> > +
> > +// FIXME: See macros.c.
> > +#ifdef TOP_RIGHT_UNDEF
> > +# error TOP_RIGHT_UNDEF should not be defined
> > +#endif
> > +
> > +#ifndef TOP_OTHER_UNDEF1
> > +# error TOP_OTHER_UNDEF1 should still be defined
> > +#endif
> > +
> > +#ifndef TOP_OTHER_UNDEF2
> > +# error TOP_OTHER_UNDEF2 should still be defined
> > +#endif
> > +
> > +#ifndef TOP_OTHER_REDEF1
> > +# error TOP_OTHER_REDEF1 should still be defined
> > +#endif
> > +int n1 = TOP_OTHER_REDEF1; // expected-warning{{ambiguous expansion of
> macro 'TOP_OTHER_REDEF1'}}
> > +// expected-note at macros_top.h:19 {{expanding this definition}}
> > +// expected-note at macros_other.h:4 {{other definition}}
> > +
> > +#ifndef TOP_OTHER_REDEF2
> > +# error TOP_OTHER_REDEF2 should still be defined
> > +#endif
> > +int n2 = TOP_OTHER_REDEF2; // ok
> > +
> > +int n3 = TOP_OTHER_DEF_RIGHT_UNDEF; // ok
> >
> > Added: cfe/trunk/test/PCH/macro-undef.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/macro-undef.cpp?rev=202560&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/test/PCH/macro-undef.cpp (added)
> > +++ cfe/trunk/test/PCH/macro-undef.cpp Fri Feb 28 18:08:04 2014
> > @@ -0,0 +1,36 @@
> > +// RUN: %clang_cc1 -emit-pch -o %t %s
> > +// RUN: %clang_cc1 -fsyntax-only -include-pch %t %s -Wuninitialized
> -verify
> > +// RUN: %clang_cc1 -fsyntax-only -include-pch %t %s -Wuninitialized
> -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s
> > +
> > +#ifndef HEADER
> > +#define HEADER
> > +
> > +#define NULL 0
> > +template<typename T>
> > +void *f() {
> > + void *p; // @11
> > + return p; // @12
> > +}
> > +#undef NULL
> > +template<typename T>
> > +void *g() {
> > + void *p; // @17
> > + return p; // @18
> > +}
> > +
> > +#else
> > +
> > +// expected-warning at 12 {{uninitialized}}
> > +// expected-note at 11 {{initialize}}
> > +// CHECK: fix-it:"{{.*}}":{11:10-11:10}:" = NULL"
> > +
> > +// expected-warning at 18 {{uninitialized}}
> > +// expected-note at 17 {{initialize}}
> > +// CHECK: fix-it:"{{.*}}":{17:10-17:10}:" = 0"
> > +
> > +int main() {
> > + f<int>(); // expected-note {{instantiation}}
> > + g<int>(); // expected-note {{instantiation}}
> > +}
> > +
> > +#endif
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140320/28477179/attachment.html>
More information about the cfe-commits
mailing list