Implement checking for macro equality, C99 6.10.3.2

llvm-svn: 38680
This commit is contained in:
Chris Lattner 2006-07-08 07:16:08 +00:00
parent e8eef3207b
commit 21284dfdd1
3 changed files with 39 additions and 10 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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.
///