diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/Lex/MacroInfo.cpp | 36 | ||||
| -rw-r--r-- | clang/Lex/Preprocessor.cpp | 4 | ||||
| -rw-r--r-- | clang/include/clang/Lex/MacroInfo.h | 9 |
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. /// |

