aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-03-26 17:17:01 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-03-26 17:17:01 +0000
commitc56fff7fd231aebf4b152f60f8f11ef91835c48a (patch)
tree22119f54c12ae692e50e7ed4930160f950e37f2f
parent1232e279b4a0d98885b9672d3bb5905488360e49 (diff)
[Preprocessor/Modules] Separate the macro directives kinds into their own MacroDirective's subclasses.
For each macro directive (define, undefine, visibility) have a separate object that gets chained to the macro directive history. This has several benefits: -No need to mutate a MacroDirective when there is a undefine/visibility directive. Stuff like PPMutationListener become unnecessary. -No need to keep extra source locations for the undef/visibility locations for the define directive object (which is the majority of the directives) -Much easier to hide/unhide a section in the macro directive history. -Easier to track the effects of the directives across different submodules. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178037 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Lex/MacroInfo.h254
-rw-r--r--include/clang/Lex/Preprocessor.h43
-rw-r--r--lib/Frontend/CompilerInstance.cpp39
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp4
-rw-r--r--lib/Lex/MacroInfo.cpp40
-rw-r--r--lib/Lex/PPDirectives.cpp70
-rw-r--r--lib/Lex/PPExpressions.cpp2
-rw-r--r--lib/Lex/PPMacroExpansion.cpp120
-rw-r--r--lib/Lex/Pragma.cpp13
-rw-r--r--lib/Lex/PreprocessingRecord.cpp15
-rw-r--r--lib/Lex/Preprocessor.cpp14
-rw-r--r--lib/Sema/SemaCodeComplete.cpp2
-rw-r--r--lib/Serialization/ASTReader.cpp69
-rw-r--r--lib/Serialization/ASTWriter.cpp136
-rw-r--r--tools/libclang/CIndex.cpp12
15 files changed, 440 insertions, 393 deletions
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index d83d0cc9f0..d7e72fb5c6 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -299,6 +299,8 @@ private:
friend class Preprocessor;
};
+class DefMacroDirective;
+
/// \brief Encapsulates changes to the "macros namespace" (the location where
/// the macro name became active, the location where it was undefined, etc.).
///
@@ -314,76 +316,56 @@ private:
/// will point to the same MacroInfo object.
///
class MacroDirective {
- MacroInfo *Info;
-
- /// \brief Previous definition, the identifier of this macro was defined to,
- /// or NULL.
+public:
+ enum Kind {
+ MD_Define,
+ MD_Undefine,
+ MD_Visibility
+ };
+
+protected:
+ /// \brief Previous macro directive for the same identifier, or NULL.
MacroDirective *Previous;
SourceLocation Loc;
- /// \brief The location where the macro was #undef'd, or an invalid location
- /// for macros that haven't been undefined.
- SourceLocation UndefLocation;
-
- /// \brief The location at which this macro was either explicitly exported
- /// from its module or marked as private.
- ///
- /// If invalid, this macro has not been explicitly given any visibility.
- SourceLocation VisibilityLocation;
+ /// \brief MacroDirective kind.
+ unsigned MDKind : 2;
/// \brief True if the macro directive was loaded from a PCH file.
bool IsFromPCH : 1;
- /// \brief True if this macro was imported from a module.
- bool IsImported : 1;
-
- /// \brief Whether the macro has public (when described in a module).
- bool IsPublic : 1;
-
- /// \brief Whether the macro definition is currently "hidden".
+ /// \brief Whether the macro directive is currently "hidden".
///
/// Note that this is transient state that is never serialized to the AST
/// file.
bool IsHidden : 1;
+ // Used by DefMacroDirective -----------------------------------------------//
+
+ /// \brief True if this macro was imported from a module.
+ bool IsImported : 1;
+
/// \brief Whether the definition of this macro is ambiguous, due to
/// multiple definitions coming in from multiple modules.
bool IsAmbiguous : 1;
- /// \brief Whether this macro changed after it was loaded from an AST file.
- bool ChangedAfterLoad : 1;
+ // Used by VisibilityMacroDirective ----------------------------------------//
-public:
- explicit MacroDirective(MacroInfo *MI)
- : Info(MI), Previous(0), Loc(MI->getDefinitionLoc()),
- IsFromPCH(false), IsImported(false), IsPublic(true), IsHidden(false),
- IsAmbiguous(false), ChangedAfterLoad(false) {
- assert(MI && "MacroInfo is null");
- }
-
- MacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported)
- : Info(MI), Previous(0), Loc(Loc),
- IsFromPCH(false), IsImported(isImported), IsPublic(true), IsHidden(false),
- IsAmbiguous(false), ChangedAfterLoad(false) {
- assert(MI && "MacroInfo is null");
- }
-
- SourceLocation getLocation() const { return Loc; }
+ /// \brief Whether the macro has public visibility (when described in a
+ /// module).
+ bool IsPublic : 1;
- /// \brief Set the location where macro was undefined. Can only be set once.
- void setUndefLoc(SourceLocation UndefLoc) {
- assert(UndefLocation.isInvalid() && "UndefLocation is already set!");
- assert(UndefLoc.isValid() && "Invalid UndefLoc!");
- UndefLocation = UndefLoc;
+ MacroDirective(Kind K, SourceLocation Loc)
+ : Previous(0), Loc(Loc), MDKind(K), IsFromPCH(false), IsHidden(false),
+ IsImported(false), IsAmbiguous(false),
+ IsPublic(true) {
}
- /// \brief The data for the macro definition.
- const MacroInfo *getInfo() const { return Info; }
- MacroInfo *getInfo() { return Info; }
+public:
+ Kind getKind() const { return Kind(MDKind); }
- /// \brief Get the location where macro was undefined.
- SourceLocation getUndefLoc() const { return UndefLocation; }
+ SourceLocation getLocation() const { return Loc; }
/// \brief Set previous definition of the macro with the same name.
void setPrevious(MacroDirective *Prev) {
@@ -396,42 +378,104 @@ public:
/// \brief Get previous definition of the macro with the same name.
MacroDirective *getPrevious() { return Previous; }
- /// \brief Find macro definition active in the specified source location. If
- /// this macro was not defined there, return NULL.
- const MacroDirective *findDirectiveAtLoc(SourceLocation L,
- SourceManager &SM) const;
+ /// \brief Return true if the macro directive was loaded from a PCH file.
+ bool isFromPCH() const { return IsFromPCH; }
- /// \brief Set the export location for this macro.
- void setVisibility(bool Public, SourceLocation Loc) {
- VisibilityLocation = Loc;
- IsPublic = Public;
+ void setIsFromPCH() { IsFromPCH = true; }
+
+ /// \brief Determine whether this macro directive is hidden.
+ bool isHidden() const { return IsHidden; }
+
+ /// \brief Set whether this macro directive is hidden.
+ void setHidden(bool Val) { IsHidden = Val; }
+
+ class DefInfo {
+ DefMacroDirective *DefDirective;
+ SourceLocation UndefLoc;
+ bool IsPublic;
+
+ public:
+ DefInfo() : DefDirective(0) { }
+
+ DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
+ bool isPublic)
+ : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) { }
+
+ const DefMacroDirective *getDirective() const { return DefDirective; }
+ DefMacroDirective *getDirective() { return DefDirective; }
+
+ inline SourceLocation getLocation() const;
+ inline MacroInfo *getMacroInfo();
+ const MacroInfo *getMacroInfo() const {
+ return const_cast<DefInfo*>(this)->getMacroInfo();
+ }
+
+ SourceLocation getUndefLocation() const { return UndefLoc; }
+ bool isUndefined() const { return UndefLoc.isValid(); }
+
+ bool isPublic() const { return IsPublic; }
+
+ bool isValid() const { return DefDirective != 0; }
+ bool isInvalid() const { return !isValid(); }
+
+ operator bool() const { return isValid(); }
+
+ inline DefInfo getPreviousDefinition(bool AllowHidden = false);
+ const DefInfo getPreviousDefinition(bool AllowHidden = false) const {
+ return const_cast<DefInfo*>(this)->getPreviousDefinition(AllowHidden);
+ }
+ };
+
+ /// \brief Traverses the macro directives history and returns the next
+ /// macro definition directive along with info about its undefined location
+ /// (if there is one) and if it is public or private.
+ DefInfo getDefinition(bool AllowHidden = false);
+ const DefInfo getDefinition(bool AllowHidden = false) const {
+ return const_cast<MacroDirective*>(this)->getDefinition(AllowHidden);
}
- /// \brief Determine whether this macro is part of the public API of its
- /// module.
- bool isPublic() const { return IsPublic; }
-
- /// \brief Determine the location where this macro was explicitly made
- /// public or private within its module.
- SourceLocation getVisibilityLocation() const { return VisibilityLocation; }
+ bool isDefined(bool AllowHidden = false) const {
+ if (const DefInfo Def = getDefinition(AllowHidden))
+ return !Def.isUndefined();
+ return false;
+ }
- /// \brief Return true if the macro directive was loaded from a PCH file.
- bool isFromPCH() const { return IsFromPCH; }
+ const MacroInfo *getMacroInfo(bool AllowHidden = false) const {
+ return getDefinition(AllowHidden).getMacroInfo();
+ }
+ MacroInfo *getMacroInfo(bool AllowHidden = false) {
+ return getDefinition(AllowHidden).getMacroInfo();
+ }
- void setIsFromPCH() { IsFromPCH = true; }
+ /// \brief Find macro definition active in the specified source location. If
+ /// this macro was not defined there, return NULL.
+ const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const;
- /// \brief True if this macro was imported from a module.
- bool isImported() const { return IsImported; }
+ static bool classof(const MacroDirective *) { return true; }
+};
- /// \brief Determine whether this macro is currently defined (and has not
- /// been #undef'd) or has been hidden.
- bool isDefined() const { return UndefLocation.isInvalid() && !IsHidden; }
+/// \brief A directive for a defined macro or a macro imported from a module.
+class DefMacroDirective : public MacroDirective {
+ MacroInfo *Info;
- /// \brief Determine whether this macro definition is hidden.
- bool isHidden() const { return IsHidden; }
+public:
+ explicit DefMacroDirective(MacroInfo *MI)
+ : MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) {
+ assert(MI && "MacroInfo is null");
+ }
- /// \brief Set whether this macro definition is hidden.
- void setHidden(bool Val) { IsHidden = Val; }
+ DefMacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported)
+ : MacroDirective(MD_Define, Loc), Info(MI) {
+ assert(MI && "MacroInfo is null");
+ IsImported = isImported;
+ }
+
+ /// \brief The data for the macro definition.
+ const MacroInfo *getInfo() const { return Info; }
+ MacroInfo *getInfo() { return Info; }
+
+ /// \brief True if this macro was imported from a module.
+ bool isImported() const { return IsImported; }
/// \brief Determine whether this macro definition is ambiguous with
/// other macro definitions.
@@ -440,15 +484,63 @@ public:
/// \brief Set whether this macro definition is ambiguous.
void setAmbiguous(bool Val) { IsAmbiguous = Val; }
- /// \brief Determine whether this macro has changed since it was loaded from
- /// an AST file.
- bool hasChangedAfterLoad() const { return ChangedAfterLoad; }
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Define;
+ }
+ static bool classof(const DefMacroDirective *) { return true; }
+};
- /// \brief Note whether this macro has changed after it was loaded from an
- /// AST file.
- void setChangedAfterLoad(bool CAL = true) { ChangedAfterLoad = CAL; }
+/// \brief A directive for an undefined macro.
+class UndefMacroDirective : public MacroDirective {
+public:
+ explicit UndefMacroDirective(SourceLocation UndefLoc)
+ : MacroDirective(MD_Undefine, UndefLoc) {
+ assert(UndefLoc.isValid() && "Invalid UndefLoc!");
+ }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Undefine;
+ }
+ static bool classof(const UndefMacroDirective *) { return true; }
};
+/// \brief A directive for setting the module visibility of a macro.
+class VisibilityMacroDirective : public MacroDirective {
+public:
+ explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
+ : MacroDirective(MD_Visibility, Loc) {
+ IsPublic = Public;
+ }
+
+ /// \brief Determine whether this macro is part of the public API of its
+ /// module.
+ bool isPublic() const { return IsPublic; }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Visibility;
+ }
+ static bool classof(const VisibilityMacroDirective *) { return true; }
+};
+
+inline SourceLocation MacroDirective::DefInfo::getLocation() const {
+ if (isInvalid())
+ return SourceLocation();
+ return DefDirective->getLocation();
+}
+
+inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
+ if (isInvalid())
+ return 0;
+ return DefDirective->getInfo();
+}
+
+inline MacroDirective::DefInfo
+MacroDirective::DefInfo::getPreviousDefinition(bool AllowHidden) {
+ if (isInvalid() || DefDirective->getPrevious() == 0)
+ return DefInfo();
+ return DefDirective->getPrevious()->getDefinition(AllowHidden);
+}
+
} // end namespace clang
#endif
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index fdff12395e..dafa497214 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -532,14 +532,14 @@ public:
/// associated with this preprocessor, if any.
PPMutationListener *getPPMutationListener() const { return Listener; }
- /// \brief Given an identifier, return the MacroInfo it is \#defined to
- /// or null if it isn't \#define'd.
+ /// \brief Given an identifier, return its latest MacroDirective if it is
+ // \#defined or null if it isn't \#define'd.
MacroDirective *getMacroDirective(IdentifierInfo *II) const {
if (!II->hasMacroDefinition())
return 0;
MacroDirective *MD = getMacroDirectiveHistory(II);
- assert(MD->getUndefLoc().isInvalid() && "Macro is undefined!");
+ assert(MD->isDefined() && "Macro is undefined!");
return MD;
}
@@ -549,7 +549,7 @@ public:
MacroInfo *getMacroInfo(IdentifierInfo *II) {
if (MacroDirective *MD = getMacroDirective(II))
- return MD->getInfo();
+ return MD->getMacroInfo();
return 0;
}
@@ -559,27 +559,20 @@ public:
/// identifiers that hadMacroDefinition().
MacroDirective *getMacroDirectiveHistory(const IdentifierInfo *II) const;
- /// \brief Specify a macro for this identifier.
- void setMacroDirective(IdentifierInfo *II, MacroDirective *MD);
- MacroDirective *setMacroDirective(IdentifierInfo *II, MacroInfo *MI,
- SourceLocation Loc, bool isImported) {
- MacroDirective *MD = AllocateMacroDirective(MI, Loc, isImported);
- setMacroDirective(II, MD);
+ /// \brief Add a directive to the macro directive history for this identifier.
+ void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD);
+ DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI,
+ SourceLocation Loc,
+ bool isImported) {
+ DefMacroDirective *MD = AllocateDefMacroDirective(MI, Loc, isImported);
+ appendMacroDirective(II, MD);
return MD;
}
- MacroDirective *setMacroDirective(IdentifierInfo *II, MacroInfo *MI) {
- return setMacroDirective(II, MI, MI->getDefinitionLoc(), false);
+ DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI){
+ return appendDefMacroDirective(II, MI, MI->getDefinitionLoc(), false);
}
/// \brief Set a MacroDirective that was loaded from a PCH file.
void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD);
- /// \brief Add a MacroInfo that was loaded from an AST file.
- void addLoadedMacroInfo(IdentifierInfo *II, MacroDirective *MD,
- MacroDirective *Hint = 0);
- /// \brief Make the given MacroInfo, that was loaded from an AST file and
- /// previously hidden, visible.
- void makeLoadedMacroInfoVisible(IdentifierInfo *II, MacroDirective *MD);
- /// \brief Undefine a macro for this identifier.
- void clearMacroInfo(IdentifierInfo *II);
/// macro_iterator/macro_begin/macro_end - This allows you to walk the macro
/// history table. Currently defined macros have
@@ -1294,8 +1287,12 @@ private:
/// \brief Allocate a new MacroInfo object.
MacroInfo *AllocateMacroInfo();
- MacroDirective *AllocateMacroDirective(MacroInfo *MI, SourceLocation Loc,
- bool isImported);
+ DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI,
+ SourceLocation Loc,
+ bool isImported);
+ UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc);
+ VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc,
+ bool isPublic);
/// \brief Release the specified MacroInfo for re-use.
///
@@ -1449,8 +1446,6 @@ private:
// Macro handling.
void HandleDefineDirective(Token &Tok);
void HandleUndefDirective(Token &Tok);
- void UndefineMacro(IdentifierInfo *II, MacroDirective *MD,
- SourceLocation UndefLoc);
// Conditional Inclusion.
void HandleIfdefDirective(Token &Tok, bool isIfndef,
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 4c4d603716..c6c850b0d6 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -923,10 +923,11 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
// If this identifier does not currently have a macro definition,
// check whether it had one on the command line.
if (!Id->hasMacroDefinition()) {
- MacroDirective *UndefMD = PP.getMacroDirectiveHistory(Id);
- for (MacroDirective *MD = UndefMD; MD; MD = MD->getPrevious()) {
-
- FileID FID = SourceMgr.getFileID(MD->getLocation());
+ MacroDirective::DefInfo LatestDef =
+ PP.getMacroDirectiveHistory(Id)->getDefinition();
+ for (MacroDirective::DefInfo Def = LatestDef; Def;
+ Def = Def.getPreviousDefinition()) {
+ FileID FID = SourceMgr.getFileID(Def.getLocation());
if (FID.isInvalid())
continue;
@@ -942,8 +943,8 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
// Complain.
PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
<< true << ConfigMacro << Mod->getFullModuleName();
- if (UndefMD->getUndefLoc().isValid())
- PP.Diag(UndefMD->getUndefLoc(), diag::note_module_def_undef_here)
+ if (LatestDef.isUndefined())
+ PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here)
<< true;
return;
}
@@ -954,10 +955,12 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
// This identifier has a macro definition. Check whether we had a definition
// on the command line.
- MacroDirective *DefMD = PP.getMacroDirective(Id);
- MacroDirective *PredefinedMD = 0;
- for (MacroDirective *MD = DefMD; MD; MD = MD->getPrevious()) {
- FileID FID = SourceMgr.getFileID(MD->getLocation());
+ MacroDirective::DefInfo LatestDef =
+ PP.getMacroDirectiveHistory(Id)->getDefinition();
+ MacroDirective::DefInfo PredefinedDef;
+ for (MacroDirective::DefInfo Def = LatestDef; Def;
+ Def = Def.getPreviousDefinition()) {
+ FileID FID = SourceMgr.getFileID(Def.getLocation());
if (FID.isInvalid())
continue;
@@ -969,32 +972,32 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
if (!StringRef(Buffer->getBufferIdentifier()).equals("<built-in>"))
continue;
- PredefinedMD = MD;
+ PredefinedDef = Def;
break;
}
// If there was no definition for this macro in the predefines buffer,
// complain.
- if (!PredefinedMD ||
- (!PredefinedMD->getLocation().isValid() &&
- PredefinedMD->getUndefLoc().isValid())) {
+ if (!PredefinedDef ||
+ (!PredefinedDef.getLocation().isValid() &&
+ PredefinedDef.getUndefLocation().isValid())) {
PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
<< false << ConfigMacro << Mod->getFullModuleName();
- PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here)
+ PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here)
<< false;
return;
}
// If the current macro definition is the same as the predefined macro
// definition, it's okay.
- if (DefMD == PredefinedMD ||
- DefMD->getInfo()->isIdenticalTo(*PredefinedMD->getInfo(), PP))
+ if (LatestDef.getMacroInfo() == PredefinedDef.getMacroInfo() ||
+ LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP))
return;
// The macro definitions differ.
PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
<< false << ConfigMacro << Mod->getFullModuleName();
- PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here)
+ PP.Diag(LatestDef.getLocation(), diag::note_module_def_undef_here)
<< false;
}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index d894939b4b..f70bd7c93e 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -318,7 +318,7 @@ void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
/// MacroDefined - This hook is called whenever a macro definition is seen.
void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) {
- const MacroInfo *MI = MD->getInfo();
+ const MacroInfo *MI = MD->getMacroInfo();
// Only print out macro definitions in -dD mode.
if (!DumpDefines ||
// Ignore __FILE__ etc.
@@ -602,7 +602,7 @@ static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) {
for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
I != E; ++I) {
if (I->first->hasMacroDefinition())
- MacrosByID.push_back(id_macro_pair(I->first, I->second->getInfo()));
+ MacrosByID.push_back(id_macro_pair(I->first, I->second->getMacroInfo()));
}
llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index 213e71132b..dc091f625b 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -108,14 +108,40 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
return true;
}
-const MacroDirective *
+MacroDirective::DefInfo MacroDirective::getDefinition(bool AllowHidden) {
+ MacroDirective *MD = this;
+ SourceLocation UndefLoc;
+ Optional<bool> isPublic;
+ for (; MD; MD = MD->getPrevious()) {
+ if (!AllowHidden && MD->isHidden())
+ continue;
+
+ if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))
+ return DefInfo(DefMD, UndefLoc,
+ !isPublic.hasValue() || isPublic.getValue());
+
+ if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {
+ UndefLoc = UndefMD->getLocation();
+ continue;
+ }
+
+ VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
+ if (!isPublic.hasValue())
+ isPublic = VisMD->isPublic();
+ }
+
+ return DefInfo();
+}
+
+const MacroDirective::DefInfo
MacroDirective::findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const {
assert(L.isValid() && "SourceLocation is invalid.");
- for (const MacroDirective *MD = this; MD; MD = MD->Previous) {
- if (MD->getLocation().isInvalid() || // For macros defined on the command line.
- SM.isBeforeInTranslationUnit(MD->getLocation(), L))
- return (MD->UndefLocation.isInvalid() ||
- SM.isBeforeInTranslationUnit(L, MD->UndefLocation)) ? MD : NULL;
+ for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {
+ if (Def.getLocation().isInvalid() || // For macros defined on the command line.
+ SM.isBeforeInTranslationUnit(Def.getLocation(), L))
+ return (!Def.isUndefined() ||
+ SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))
+ ? Def : DefInfo();
}
- return NULL;
+ return DefInfo();
}
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 7020da3940..3fc19e41f8 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -70,11 +70,26 @@ MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L,
return MI;
}
-MacroDirective *Preprocessor::AllocateMacroDirective(MacroInfo *MI,
- SourceLocation Loc,
- bool isImported) {
- MacroDirective *MD = BP.Allocate<MacroDirective>();
- new (MD) MacroDirective(MI, Loc, isImported);
+DefMacroDirective *
+Preprocessor::AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc,
+ bool isImported) {
+ DefMacroDirective *MD = BP.Allocate<DefMacroDirective>();
+ new (MD) DefMacroDirective(MI, Loc, isImported);
+ return MD;
+}
+
+UndefMacroDirective *
+Preprocessor::AllocateUndefMacroDirective(SourceLocation UndefLoc) {
+ UndefMacroDirective *MD = BP.Allocate<UndefMacroDirective>();
+ new (MD) UndefMacroDirective(UndefLoc);
+ return MD;
+}
+
+VisibilityMacroDirective *
+Preprocessor::AllocateVisibilityMacroDirective(SourceLocation Loc,
+ bool isPublic) {
+ VisibilityMacroDirective *MD = BP.Allocate<VisibilityMacroDirective>();
+ new (MD) VisibilityMacroDirective(Loc, isPublic);
return MD;
}
@@ -1130,15 +1145,8 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
}
// Note that this macro has now been exported.
- MD->setVisibility(/*IsPublic=*/true, MacroNameTok.getLocation());
-
- // If this macro directive came from a PCH file, mark it as having changed
- // since serialization.
- if (MD->isFromPCH()) {
- MD->setChangedAfterLoad();
- assert(II->isFromAST());
- II->setChangedSinceDeserialization();
- }
+ appendMacroDirective(II, AllocateVisibilityMacroDirective(
+ MacroNameTok.getLocation(), /*IsPublic=*/true));
}
/// \brief Handle a #private directive.
@@ -1164,15 +1172,8 @@ void Preprocessor::HandleMacroPrivateDirective(Token &Tok) {
}
// Note that this macro has now been marked private.
- MD->setVisibility(/*IsPublic=*/false, MacroNameTok.getLocation());
-
- // If this macro directive came from a PCH file, mark it as having changed
- // since serialization.
- if (MD->isFromPCH()) {
- MD->setChangedAfterLoad();
- assert(II->isFromAST());
- II->setChangedSinceDeserialization();
- }
+ appendMacroDirective(II, AllocateVisibilityMacroDirective(
+ MacroNameTok.getLocation(), /*IsPublic=*/false));
}
//===----------------------------------------------------------------------===//
@@ -1960,7 +1961,8 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) {
WarnUnusedMacroLocs.erase(OtherMI->getDefinitionLoc());
}
- MacroDirective *MD = setMacroDirective(MacroNameTok.getIdentifierInfo(), MI);
+ DefMacroDirective *MD =
+ appendDefMacroDirective(MacroNameTok.getIdentifierInfo(), MI);
assert(!MI->isUsed());
// If we need warning for not using the macro, add its location in the
@@ -1994,7 +1996,7 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
// Okay, we finally have a valid identifier to undef.
MacroDirective *MD = getMacroDirective(MacroNameTok.getIdentifierInfo());
- const MacroInfo *MI = MD ? MD->getInfo() : 0;
+ const MacroInfo *MI = MD ? MD->getMacroInfo() : 0;
// If the callbacks want to know, tell them about the macro #undef.
// Note: no matter if the macro was defined or not.
@@ -2010,20 +2012,8 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
if (MI->isWarnIfUnused())
WarnUnusedMacroLocs.erase(MI->getDefinitionLoc());
- UndefineMacro(MacroNameTok.getIdentifierInfo(), MD,
- MacroNameTok.getLocation());
-}
-
-void Preprocessor::UndefineMacro(IdentifierInfo *II, MacroDirective *MD,
- SourceLocation UndefLoc) {
- MD->setUndefLoc(UndefLoc);
- if (MD->isFromPCH()) {
- MD->setChangedAfterLoad();
- if (Listener)
- Listener->UndefinedMacro(MD);
- }
-
- clearMacroInfo(II);
+ appendMacroDirective(MacroNameTok.getIdentifierInfo(),
+ AllocateUndefMacroDirective(MacroNameTok.getLocation()));
}
@@ -2058,7 +2048,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef,
IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
MacroDirective *MD = getMacroDirective(MII);
- MacroInfo *MI = MD ? MD->getInfo() : 0;
+ MacroInfo *MI = MD ? MD->getMacroInfo() : 0;
if (CurPPLexer->getConditionalStackDepth() == 0) {
// If the start of a top-level #ifdef and if the macro is not defined,
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 27ad7b4a1b..d9ce8bff23 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -116,7 +116,7 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
// If there is a macro, mark it used.
if (Result.Val != 0 && ValueLive) {
Macro = PP.getMacroDirective(II);
- PP.markMacroAsUsed(Macro->getInfo());
+ PP.markMacroAsUsed(Macro->getMacroInfo());
}
// Invoke the 'defined' callback.
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 868820b400..bb2634ffb6 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -41,15 +41,17 @@ Preprocessor::getMacroDirectiveHistory(const IdentifierInfo *II) const {
return Pos->second;
}
-/// \brief Specify a macro for this identifier.
-void Preprocessor::setMacroDirective(IdentifierInfo *II, MacroDirective *MD) {
+void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){
assert(MD && "MacroDirective should be non-zero!");
+ assert(!MD->getPrevious() && "Already attached to a MacroDirective history.");
MacroDirective *&StoredMD = Macros[II];
MD->setPrevious(StoredMD);
StoredMD = MD;
- II->setHasMacroDefinition(true);
- if (II->isFromAST())
+ II->setHasMacroDefinition(MD->isDefined());
+ bool isImportedMacro = isa<DefMacroDirective>(MD) &&
+ cast<DefMacroDirective>(MD)->isImported();
+ if (II->isFromAST() && !isImportedMacro)
II->setChangedSinceDeserialization();
}
@@ -66,112 +68,6 @@ void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II,
II->setHasMacroDefinition(false);
}
-void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroDirective *MD,
- MacroDirective *Hint) {
- assert(MD && "Missing macro?");
- assert(MD->isImported() && "Macro is not from an AST?");
- assert(!MD->getPrevious() && "Macro already in chain?");
-
- MacroDirective *&StoredMD = Macros[II];
-
- // Easy case: this is the first macro definition for this macro.
- if (!StoredMD) {
- StoredMD = MD;
-
- if (MD->isDefined())
- II->setHasMacroDefinition(true);
- return;
- }
-
- // If this macro is a definition and this identifier has been neither
- // defined nor undef'd in the current translation unit, add this macro
- // to the end of the chain of definitions.
- if (MD->isDefined() && StoredMD->isImported()) {
- // Simple case: if this is the first actual definition, just put it at
- // th beginning.
- if (!StoredMD->isDefined()) {
- MD->setPrevious(StoredMD);
- StoredMD = MD;
-
- II->setHasMacroDefinition(true);
- return;
- }
-
- // Find the end of the definition chain.
- MacroDirective *Prev;
- MacroDirective *PrevPrev = StoredMD;
- bool Ambiguous = StoredMD->isAmbiguous();
- bool MatchedOther = false;
- do {
- Prev = PrevPrev;
-
- // If the macros are not identical, we have an ambiguity.
- if (!Prev->getInfo()->isIdenticalTo(*MD->getInfo(), *this)) {
- if (!Ambiguous) {
- Ambiguous = true;
- StoredMD->setAmbiguous(true);
- }
- } else {
- MatchedOther = true;
- }
- } while ((PrevPrev = Prev->getPrevious()) &&
- PrevPrev->isDefined());
-
- // If there are ambiguous definitions, and we didn't match any other
- // definition, then mark us as ambiguous.
- if (Ambiguous && !MatchedOther)
- MD->setAmbiguous(true);
-
- // Wire this macro information into the chain.
- MD->setPrevious(Prev->getPrevious());
- Prev->setPrevious(MD);
- return;
- }
-
- // The macro is not a definition; put it at the end of the list.
- MacroDirective *Prev = Hint? Hint : StoredMD;
- while (Prev->getPrevious())
- Prev = Prev->getPrevious();
- Prev->setPrevious(MD);
-}
-
-void Preprocessor::makeLoadedMacroInfoVisible(IdentifierInfo *II,
- MacroDirective *MD) {
- assert(MD->isImported() && "Macro must be from the AST");
-
- MacroDirective *&StoredMD = Macros[II];
- if (StoredMD == MD) {
- // Easy case: this is the first macro anyway.
- II->setHasMacroDefinition(MD->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 or hidden
- // would be quadratic, but it's extremely rare.
- MacroDirective *Prev = StoredMD;
- while (Prev->getPrevious() != MD)
- Prev = Prev-&