diff options
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 9 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 3 | ||||
-rw-r--r-- | lib/Lex/MacroInfo.cpp | 36 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 4 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 3 | ||||
-rw-r--r-- | test/Modules/Inputs/macros_left.h | 2 | ||||
-rw-r--r-- | test/Modules/Inputs/macros_right.h | 2 | ||||
-rw-r--r-- | test/Modules/macros.c | 1 | ||||
-rw-r--r-- | test/Preprocessor/macro_misc.c | 14 |
9 files changed, 57 insertions, 17 deletions
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index d7e72fb5c6..64323b7c76 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -145,9 +145,12 @@ public: /// \brief 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; + /// \param Syntactically if true, the macro definitions can be identical even + /// if they use different identifiers for the function macro parameters. + /// Otherwise the comparison is lexical and this implements the rules in + /// C99 6.10.3. + bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, + bool Syntactically) const; /// \brief Set or clear the isBuiltinMacro flag. void setIsBuiltinMacro(bool Val = true) { diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index b27c06a19c..fce3d33780 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -991,7 +991,8 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, // If the current macro definition is the same as the predefined macro // definition, it's okay. if (LatestDef.getMacroInfo() == PredefinedDef.getMacroInfo() || - LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP)) + LatestDef.getMacroInfo()->isIdenticalTo(*PredefinedDef.getMacroInfo(),PP, + /*Syntactically=*/true)) return; // The macro definitions differ. diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index dc091f625b..5abafe1cb7 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -61,11 +61,17 @@ unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const { return DefinitionLength; } -// 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 { +/// \brief Return true if the specified macro definition is equal to +/// this macro in spelling, arguments, and whitespace. +/// +/// \param Syntactically if true, the macro definitions can be identical even +/// if they use different identifiers for the function macro parameters. +/// Otherwise the comparison is lexical and this implements the rules in +/// C99 6.10.3. +bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, + bool Syntactically) const { + bool Lexically = !Syntactically; + // Check # tokens in replacement, number of args, and various flags all match. if (ReplacementTokens.size() != Other.ReplacementTokens.size() || getNumArgs() != Other.getNumArgs() || @@ -74,10 +80,12 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const { isGNUVarargs() != Other.isGNUVarargs()) return false; - // Check arguments. - for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end(); - I != E; ++I, ++OI) - if (*I != *OI) return false; + if (Lexically) { + // Check arguments. + for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end(); + I != E; ++I, ++OI) + if (*I != *OI) return false; + } // Check all the tokens. for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) { @@ -95,7 +103,15 @@ bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const { // If this is an identifier, it is easy. if (A.getIdentifierInfo() || B.getIdentifierInfo()) { - if (A.getIdentifierInfo() != B.getIdentifierInfo()) + if (A.getIdentifierInfo() == B.getIdentifierInfo()) + continue; + if (Lexically) + return false; + // With syntactic equivalence the parameter names can be different as long + // as they are used in the same place. + int AArgNum = getArgumentNum(A.getIdentifierInfo()); + int BArgNum = Other.getArgumentNum(B.getIdentifierInfo()); + if (AArgNum == -1 || AArgNum != BArgNum) return false; continue; } diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 3fc19e41f8..07c1867010 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1949,9 +1949,9 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) { if (OtherMI->isBuiltinMacro()) Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro); // Macros must be identical. This means all tokens and whitespace - // separation must be the same. C99 6.10.3.2. + // separation must be the same. C99 6.10.3p2. else if (!OtherMI->isAllowRedefinitionsWithoutWarning() && - !MI->isIdenticalTo(*OtherMI, *this)) { + !MI->isIdenticalTo(*OtherMI, *this, /*Syntactic=*/LangOpts.MicrosoftExt)) { Diag(MI->getDefinitionLoc(), diag::ext_pp_macro_redef) << MacroNameTok.getIdentifierInfo(); Diag(OtherMI->getDefinitionLoc(), diag::note_previous_definition); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 4c2d2197e4..4c4277c30f 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1604,7 +1604,8 @@ void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD, MacroDirective::DefInfo PrevDef = Prev->getDefinition(); MacroInfo *PrevMI = PrevDef.getMacroInfo(); MacroInfo *NewMI = DefMD->getInfo(); - if (NewMI != PrevMI && !PrevMI->isIdenticalTo(*NewMI, PP)) { + if (NewMI != PrevMI && !PrevMI->isIdenticalTo(*NewMI, PP, + /*Syntactically=*/true)) { // Before marking the macros as ambiguous, check if this is a case where // the system macro uses a not identical definition compared to a macro // from the clang headers. For example: diff --git a/test/Modules/Inputs/macros_left.h b/test/Modules/Inputs/macros_left.h index a8aac75a2f..076b0464e6 100644 --- a/test/Modules/Inputs/macros_left.h +++ b/test/Modules/Inputs/macros_left.h @@ -12,3 +12,5 @@ #define LEFT_RIGHT_DIFFERENT3 float #define LEFT_RIGHT_DIFFERENT float + +#define FN_ADD(a,b) (a+b) diff --git a/test/Modules/Inputs/macros_right.h b/test/Modules/Inputs/macros_right.h index 445f579cf6..dbbd2c3643 100644 --- a/test/Modules/Inputs/macros_right.h +++ b/test/Modules/Inputs/macros_right.h @@ -15,3 +15,5 @@ #undef TOP_RIGHT_REDEF #define TOP_RIGHT_REDEF float + +#define FN_ADD(x, y) (x+y) diff --git a/test/Modules/macros.c b/test/Modules/macros.c index c715ec9651..fc448d9989 100644 --- a/test/Modules/macros.c +++ b/test/Modules/macros.c @@ -125,6 +125,7 @@ void test2() { void test3() { double d; LEFT_RIGHT_DIFFERENT *dp = &d; // okay + int x = FN_ADD(1,2); } #ifndef TOP_RIGHT_UNDEF diff --git a/test/Preprocessor/macro_misc.c b/test/Preprocessor/macro_misc.c index 53d99821cc..3feaa210f7 100644 --- a/test/Preprocessor/macro_misc.c +++ b/test/Preprocessor/macro_misc.c @@ -21,3 +21,17 @@ #define FUNC_LIKE3(a) ( a) // expected-note {{previous definition is here}} #define FUNC_LIKE3(a) (a) // expected-warning {{'FUNC_LIKE3' macro redefined}} +// RUN: %clang_cc1 -fms-extensions -DMS_EXT %s -Eonly -verify +#ifndef MS_EXT +// This should under C99. +#define FUNC_LIKE4(a,b) (a+b) // expected-note {{previous definition is here}} +#define FUNC_LIKE4(x,y) (x+y) // expected-warning {{'FUNC_LIKE4' macro redefined}} +#else +// This shouldn't under MS extensions. +#define FUNC_LIKE4(a,b) (a+b) +#define FUNC_LIKE4(x,y) (x+y) + +// This should. +#define FUNC_LIKE5(a,b) (a+b) // expected-note {{previous definition is here}} +#define FUNC_LIKE5(x,y) (y+x) // expected-warning {{'FUNC_LIKE5' macro redefined}} +#endif |