[cfe-commits] r165746 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticLexKinds.td include/clang/Lex/MacroInfo.h lib/Lex/MacroInfo.cpp lib/Lex/PPMacroExpansion.cpp lib/Serialization/ASTReader.cpp test/Modules/Inputs/macros_left.h test/Modules/Inputs/macros_right.h test/Modules/Inputs/macros_top.h test/Modules/macros.c
Douglas Gregor
dgregor at apple.com
Thu Oct 11 14:07:40 PDT 2012
Author: dgregor
Date: Thu Oct 11 16:07:39 2012
New Revision: 165746
URL: http://llvm.org/viewvc/llvm-project?rev=165746&view=rev
Log:
Diagnose the expansion of ambiguous macro definitions. This can happen
only with modules, when two disjoint modules #define the same
identifier to different token sequences.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticGroups.td
cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
cfe/trunk/include/clang/Lex/MacroInfo.h
cfe/trunk/lib/Lex/MacroInfo.cpp
cfe/trunk/lib/Lex/PPMacroExpansion.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/test/Modules/Inputs/macros_left.h
cfe/trunk/test/Modules/Inputs/macros_right.h
cfe/trunk/test/Modules/Inputs/macros_top.h
cfe/trunk/test/Modules/macros.c
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu Oct 11 16:07:39 2012
@@ -212,6 +212,7 @@
// Preprocessor warnings.
def : DiagGroup<"builtin-macro-redefined">;
+def AmbiguousMacro : DiagGroup<"ambiguous-macro">;
// Just silence warnings about -Wstrict-aliasing for now.
def : DiagGroup<"strict-aliasing=0">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Thu Oct 11 16:07:39 2012
@@ -228,6 +228,12 @@
def warn_pp_undef_identifier : Warning<
"%0 is not defined, evaluates to 0">,
InGroup<DiagGroup<"undef">>, DefaultIgnore;
+def warn_pp_ambiguous_macro : Warning<
+ "ambiguous expansion of macro %0">, InGroup<AmbiguousMacro>;
+def note_pp_ambiguous_macro_chosen : Note<
+ "expanding this definition of %0">;
+def note_pp_ambiguous_macro_other : Note<
+ "other definition of %0">;
def pp_invalid_string_literal : Warning<
"invalid string literal, ignoring final '\\'">;
Modified: cfe/trunk/include/clang/Lex/MacroInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/MacroInfo.h?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/trunk/include/clang/Lex/MacroInfo.h Thu Oct 11 16:07:39 2012
@@ -111,6 +111,10 @@
/// file.
bool IsHidden : 1;
+ /// \brief Whether the definition of this macro is ambiguous, due to
+ /// multiple definitions coming in from multiple modules.
+ bool IsAmbiguous : 1;
+
~MacroInfo() {
assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
}
@@ -340,6 +344,13 @@
/// \brief Set whether this macro definition is hidden.
void setHidden(bool Val) { IsHidden = Val; }
+ /// \brief Determine whether this macro definition is ambiguous with
+ /// other macro definitions.
+ bool isAmbiguous() const { return IsAmbiguous; }
+
+ /// \brief Set whether this macro definition is ambiguous.
+ void setAmbiguous(bool Val) { IsAmbiguous = Val; }
+
private:
unsigned getDefinitionLengthSlow(SourceManager &SM) const;
};
Modified: cfe/trunk/lib/Lex/MacroInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/MacroInfo.cpp?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/MacroInfo.cpp (original)
+++ cfe/trunk/lib/Lex/MacroInfo.cpp Thu Oct 11 16:07:39 2012
@@ -32,7 +32,8 @@
IsAllowRedefinitionsWithoutWarning(false),
IsWarnIfUnused(false),
IsPublic(true),
- IsHidden(false) {
+ IsHidden(false),
+ IsAmbiguous(false) {
}
MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator)
@@ -56,7 +57,8 @@
IsAllowRedefinitionsWithoutWarning(MI.IsAllowRedefinitionsWithoutWarning),
IsWarnIfUnused(MI.IsWarnIfUnused),
IsPublic(MI.IsPublic),
- IsHidden(MI.IsHidden) {
+ IsHidden(MI.IsHidden),
+ IsAmbiguous(MI.IsAmbiguous) {
setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
}
Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Oct 11 16:07:39 2012
@@ -89,15 +89,25 @@
// Find the end of the definition chain.
MacroInfo *Prev = StoredMI;
MacroInfo *PrevPrev;
- bool Ambiguous = false;
+ bool Ambiguous = StoredMI->isAmbiguous();
+ bool MatchedOther = false;
do {
// If the macros are not identical, we have an ambiguity.
- if (!Prev->isIdenticalTo(*MI, *this))
- Ambiguous = true;
+ if (!Prev->isIdenticalTo(*MI, *this)) {
+ if (!Ambiguous) {
+ Ambiguous = true;
+ StoredMI->setAmbiguous(true);
+ }
+ } else {
+ MatchedOther = true;
+ }
} while ((PrevPrev = Prev->getPreviousDefinition()) &&
PrevPrev->isDefined());
- // FIXME: Actually use the ambiguity information for something.
+ // If there are ambiguous definitions, and we didn't match any other
+ // definition, then mark us as ambiguous.
+ if (Ambiguous && !MatchedOther)
+ MI->setAmbiguous(true);
// Wire this macro information into the chain.
MI->setPreviousDefinition(Prev->getPreviousDefinition());
@@ -360,7 +370,23 @@
}
}
}
-
+
+ // If the macro definition is ambiguous, complain.
+ if (MI->isAmbiguous()) {
+ Diag(Identifier, diag::warn_pp_ambiguous_macro)
+ << Identifier.getIdentifierInfo();
+ Diag(MI->getDefinitionLoc(), diag::note_pp_ambiguous_macro_chosen)
+ << Identifier.getIdentifierInfo();
+ for (MacroInfo *PrevMI = MI->getPreviousDefinition();
+ PrevMI && PrevMI->isDefined();
+ PrevMI = PrevMI->getPreviousDefinition()) {
+ if (PrevMI->isAmbiguous()) {
+ Diag(PrevMI->getDefinitionLoc(), diag::note_pp_ambiguous_macro_other)
+ << Identifier.getIdentifierInfo();
+ }
+ }
+ }
+
// If we started lexing a macro, enter the macro expansion body.
// If this macro expands to no tokens, don't bother to push it onto the
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Oct 11 16:07:39 2012
@@ -1254,6 +1254,24 @@
SmallVector<IdentifierInfo*, 16> MacroArgs;
MacroInfo *Macro = 0;
+ // RAII object to add the loaded macro information once we're done
+ // adding tokens.
+ struct AddLoadedMacroInfoRAII {
+ Preprocessor &PP;
+ MacroInfo *Hint;
+ MacroInfo *MI;
+ IdentifierInfo *II;
+
+ AddLoadedMacroInfoRAII(Preprocessor &PP, MacroInfo *Hint)
+ : PP(PP), Hint(Hint), MI(), II() { }
+ ~AddLoadedMacroInfoRAII( ) {
+ if (MI) {
+ // Finally, install the macro.
+ PP.addLoadedMacroInfo(II, MI, Hint);
+ }
+ }
+ } AddLoadedMacroInfo(PP, Hint);
+
while (true) {
unsigned Code = Stream.ReadCode();
switch (Code) {
@@ -1370,8 +1388,9 @@
}
MI->setHidden(Hidden);
- // Finally, install the macro.
- PP.addLoadedMacroInfo(II, MI, Hint);
+ // Make sure we install the macro once we're done.
+ AddLoadedMacroInfo.MI = MI;
+ AddLoadedMacroInfo.II = II;
// Remember that we saw this macro last so that we add the tokens that
// form its body to it.
Modified: cfe/trunk/test/Modules/Inputs/macros_left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/macros_left.h?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/macros_left.h (original)
+++ cfe/trunk/test/Modules/Inputs/macros_left.h Thu Oct 11 16:07:39 2012
@@ -7,6 +7,8 @@
#define LEFT_RIGHT_IDENTICAL int
-#define LEFT_RIGHT_DIFFERENT float
+
#define LEFT_RIGHT_DIFFERENT2 float
#define LEFT_RIGHT_DIFFERENT3 float
+
+#define LEFT_RIGHT_DIFFERENT float
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=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/macros_right.h (original)
+++ cfe/trunk/test/Modules/Inputs/macros_right.h Thu Oct 11 16:07:39 2012
@@ -1,8 +1,8 @@
#include "macros_top.h"
#define RIGHT unsigned short
-#undef TOP_RIGHT_REDEF
-#define TOP_RIGHT_REDEF float
+
+
@@ -13,3 +13,5 @@
#define LEFT_RIGHT_DIFFERENT2 int
#define LEFT_RIGHT_DIFFERENT3 int
+#undef TOP_RIGHT_REDEF
+#define TOP_RIGHT_REDEF float
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=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/macros_top.h (original)
+++ cfe/trunk/test/Modules/Inputs/macros_top.h Thu Oct 11 16:07:39 2012
@@ -2,4 +2,12 @@
#define TOP_LEFT_UNDEF 1
+
+
+
+
+
+
+
+
#define TOP_RIGHT_REDEF int
Modified: cfe/trunk/test/Modules/macros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/macros.c?rev=165746&r1=165745&r2=165746&view=diff
==============================================================================
--- cfe/trunk/test/Modules/macros.c (original)
+++ cfe/trunk/test/Modules/macros.c Thu Oct 11 16:07:39 2012
@@ -7,8 +7,14 @@
// RUN: %clang_cc1 -E -fmodules -x objective-c -fmodule-cache-path %t %s | FileCheck -check-prefix CHECK-PREPROCESSED %s
// FIXME: When we have a syntax for modules in C, use that.
// These notes come from headers in modules, and are bogus.
+
// FIXME: expected-note{{previous definition is here}}
-// FIXME: expected-note{{previous definition is here}}
+// expected-note{{other definition of 'LEFT_RIGHT_DIFFERENT'}}
+// expected-note{{expanding this definition of 'TOP_RIGHT_REDEF'}}
+// FIXME: expected-note{{previous definition is here}} \
+// expected-note{{expanding this definition of 'LEFT_RIGHT_DIFFERENT'}}
+
+// expected-note{{other definition of 'TOP_RIGHT_REDEF'}}
@__experimental_modules_import macros;
@@ -109,11 +115,11 @@
int i;
float f;
double d;
- TOP_RIGHT_REDEF *ip = &i; // FIXME: warning
+ TOP_RIGHT_REDEF *ip = &i; // expected-warning{{ambiguous expansion of macro 'TOP_RIGHT_REDEF'}}
LEFT_RIGHT_IDENTICAL *ip2 = &i;
- LEFT_RIGHT_DIFFERENT *fp = &f; // FIXME: warning
- LEFT_RIGHT_DIFFERENT2 *dp = &d; // okay
+ LEFT_RIGHT_DIFFERENT *fp = &f; // expected-warning{{ambiguous expansion of macro 'LEFT_RIGHT_DIFFERENT'}}
+ LEFT_RIGHT_DIFFERENT2 *dp = &d;
int LEFT_RIGHT_DIFFERENT3;
}
More information about the cfe-commits
mailing list