Fix isInSystemMacro to handle pasted macros
Token pasted by the preprocessor (through ##) have a Spelling pointing to scratch buffer. As a result they are not recognized at system macro, even though the pasting happened in a system macro. Fix that by looking into the parent macro if the original lookup finds a scratch buffer. Differential Revision: https://reviews.llvm.org/D55782 This effectively fixes https://bugs.llvm.org/show_bug.cgi?id=35268, llvm-svn: 352838
This commit is contained in:
@@ -1440,6 +1440,12 @@ public:
|
||||
return Filename.equals("<command line>");
|
||||
}
|
||||
|
||||
/// Returns whether \p Loc is located in a <scratch space> file.
|
||||
bool isWrittenInScratchSpace(SourceLocation Loc) const {
|
||||
StringRef Filename(getPresumedLoc(Loc).getFilename());
|
||||
return Filename.equals("<scratch space>");
|
||||
}
|
||||
|
||||
/// Returns if a SourceLocation is in a system header.
|
||||
bool isInSystemHeader(SourceLocation Loc) const {
|
||||
return isSystem(getFileCharacteristic(Loc));
|
||||
@@ -1452,7 +1458,17 @@ public:
|
||||
|
||||
/// Returns whether \p Loc is expanded from a macro in a system header.
|
||||
bool isInSystemMacro(SourceLocation loc) const {
|
||||
return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc));
|
||||
if(!loc.isMacroID())
|
||||
return false;
|
||||
|
||||
// This happens when the macro is the result of a paste, in that case
|
||||
// its spelling is the scratch memory, so we take the parent context.
|
||||
if (isWrittenInScratchSpace(getSpellingLoc(loc))) {
|
||||
return isInSystemHeader(getSpellingLoc(getImmediateMacroCallerLoc(loc)));
|
||||
}
|
||||
else {
|
||||
return isInSystemHeader(getSpellingLoc(loc));
|
||||
}
|
||||
}
|
||||
|
||||
/// The size of the SLocEntry that \p FID represents.
|
||||
|
||||
13
clang/test/Misc/no-warn-in-system-macro.c
Normal file
13
clang/test/Misc/no-warn-in-system-macro.c
Normal file
@@ -0,0 +1,13 @@
|
||||
// RUN: %clang_cc1 -isystem %S -Wdouble-promotion -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s
|
||||
// CHECK-NOT: warning:
|
||||
|
||||
#include <no-warn-in-system-macro.c.inc>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
double foo = 1.0;
|
||||
|
||||
if (isnan(foo))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
9
clang/test/Misc/no-warn-in-system-macro.c.inc
Normal file
9
clang/test/Misc/no-warn-in-system-macro.c.inc
Normal file
@@ -0,0 +1,9 @@
|
||||
extern int __isnanf(float f);
|
||||
extern int __isnan(double f);
|
||||
extern int __isnanl(long double f);
|
||||
#define isnan(x) \
|
||||
(sizeof (x) == sizeof (float) \
|
||||
? __isnanf (x) \
|
||||
: sizeof (x) == sizeof (double) \
|
||||
? __isnan (x) : __isnanl (x))
|
||||
|
||||
21
clang/test/Misc/warn-in-system-macro-def.c
Normal file
21
clang/test/Misc/warn-in-system-macro-def.c
Normal file
@@ -0,0 +1,21 @@
|
||||
// RUN: %clang_cc1 -isystem %S -Wdouble-promotion -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s
|
||||
// CHECK: warning:
|
||||
// CHECK: expanded from macro 'ISNAN'
|
||||
// CHECK: expanded from macro 'isnan'
|
||||
|
||||
#include <warn-in-system-macro-def.c.inc>
|
||||
|
||||
#define isnan(x) \
|
||||
(sizeof (x) == sizeof (float) \
|
||||
? __isnanf (x) \
|
||||
: sizeof (x) == sizeof (double) \
|
||||
? __isnan (x) : __isnanl (x))
|
||||
|
||||
int main(void)
|
||||
{
|
||||
double foo = 1.0;
|
||||
|
||||
if (ISNAN(foo))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
4
clang/test/Misc/warn-in-system-macro-def.c.inc
Normal file
4
clang/test/Misc/warn-in-system-macro-def.c.inc
Normal file
@@ -0,0 +1,4 @@
|
||||
extern int __isnanf(float f);
|
||||
extern int __isnan(double f);
|
||||
extern int __isnanl(long double f);
|
||||
#define ISNAN isnan
|
||||
Reference in New Issue
Block a user