summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/Lex/MacroInfo.cpp36
-rw-r--r--clang/Lex/Preprocessor.cpp4
-rw-r--r--clang/include/clang/Lex/MacroInfo.h9
3 files changed, 39 insertions, 10 deletions
diff --git a/clang/Lex/MacroInfo.cpp b/clang/Lex/MacroInfo.cpp
index 28579a46bc0..f5ce986a570 100644
--- a/clang/Lex/MacroInfo.cpp
+++ b/clang/Lex/MacroInfo.cpp
@@ -12,13 +12,41 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/Preprocessor.h"
#include <iostream>
using namespace llvm;
using namespace clang;
-/// isEqualTo - Return true if the specified macro definition is equal to this
-/// macro in spelling, arguments, and whitespace. This is used to emit
-/// duplicate definition warnings.
-bool MacroInfo::isEqualTo(const MacroInfo &Other) const {
+/// isIdenticalTo - Return true if the specified macro definition is equal to
+/// this macro in spelling, arguments, and whitespace. This is used to emit
+/// duplicate definition warnings. This implements the rules in C99 6.10.3.
+bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
+ // TODO: Check param count, variadic, function likeness.
+
+ // Check # tokens in replacement match.
+ if (ReplacementTokens.size() != Other.ReplacementTokens.size())
+ return false;
+
+ // Check all the tokens.
+ for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
+ const LexerToken &A = ReplacementTokens[i];
+ const LexerToken &B = Other.ReplacementTokens[i];
+ if (A.getKind() != B.getKind() ||
+ A.isAtStartOfLine() != B.isAtStartOfLine() ||
+ A.hasLeadingSpace() != B.hasLeadingSpace())
+ return false;
+
+ // If this is an identifier, it is easy.
+ if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
+ if (A.getIdentifierInfo() != B.getIdentifierInfo())
+ return false;
+ continue;
+ }
+
+ // Otherwise, check the spelling.
+ if (PP.getSpelling(A) != PP.getSpelling(B))
+ return false;
+ }
+
return true;
}
diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp
index 66acd6c7bd5..6aa6fe273f3 100644
--- a/clang/Lex/Preprocessor.cpp
+++ b/clang/Lex/Preprocessor.cpp
@@ -1400,8 +1400,8 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok) {
Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used);
// Macros must be identical. This means all tokes and whitespace separation
- // must be the same.
- if (!MI->isEqualTo(*OtherMI)) {
+ // must be the same. C99 6.10.3.2.
+ if (!MI->isIdenticalTo(*OtherMI, *this)) {
Diag(MI->getDefinitionLoc(), diag::ext_pp_macro_redef,
MacroNameTok.getIdentifierInfo()->getName());
Diag(OtherMI->getDefinitionLoc(), diag::ext_pp_macro_redef2);
diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h
index ca668a5ae6a..7fd4be2f9e8 100644
--- a/clang/include/clang/Lex/MacroInfo.h
+++ b/clang/include/clang/Lex/MacroInfo.h
@@ -19,6 +19,7 @@
namespace llvm {
namespace clang {
+ class Preprocessor;
/// MacroInfo - Each identifier that is #define'd has an instance of this class
/// associated with it, used to implement macro expansion.
@@ -57,10 +58,10 @@ public:
///
SourceLocation getDefinitionLoc() const { return Location; }
- /// isEqualTo - Return true if the specified macro definition is equal to this
- /// macro in spelling, arguments, and whitespace. This is used to emit
- /// duplicate definition warnings.
- bool isEqualTo(const MacroInfo &Other) const;
+ /// isIdenticalTo - Return true if the specified macro definition is equal to
+ /// this macro in spelling, arguments, and whitespace. This is used to emit
+ /// duplicate definition warnings. This implements the rules in C99 6.10.3.
+ bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const;
/// setIsBuiltinMacro - Set or clear the isBuiltinMacro flag.
///
OpenPOWER on IntegriCloud