Index: cfe/trunk/include/clang/Basic/SourceManager.h =================================================================== --- cfe/trunk/include/clang/Basic/SourceManager.h +++ cfe/trunk/include/clang/Basic/SourceManager.h @@ -1440,6 +1440,12 @@ return Filename.equals(""); } + /// Returns whether \p Loc is located in a file. + bool isWrittenInScratchSpace(SourceLocation Loc) const { + StringRef Filename(getPresumedLoc(Loc).getFilename()); + return Filename.equals(""); + } + /// Returns if a SourceLocation is in a system header. bool isInSystemHeader(SourceLocation Loc) const { return isSystem(getFileCharacteristic(Loc)); @@ -1452,7 +1458,17 @@ /// 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. Index: cfe/trunk/test/Misc/no-warn-in-system-macro.c =================================================================== --- cfe/trunk/test/Misc/no-warn-in-system-macro.c +++ cfe/trunk/test/Misc/no-warn-in-system-macro.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -isystem %S -Wdouble-promotion -fsyntax-only %s 2>&1 | FileCheck -allow-empty %s +// CHECK-NOT: warning: + +#include + +int main(void) +{ + double foo = 1.0; + + if (isnan(foo)) + return 1; + return 0; +} Index: cfe/trunk/test/Misc/no-warn-in-system-macro.c.inc =================================================================== --- cfe/trunk/test/Misc/no-warn-in-system-macro.c.inc +++ cfe/trunk/test/Misc/no-warn-in-system-macro.c.inc @@ -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)) + Index: cfe/trunk/test/Misc/warn-in-system-macro-def.c =================================================================== --- cfe/trunk/test/Misc/warn-in-system-macro-def.c +++ cfe/trunk/test/Misc/warn-in-system-macro-def.c @@ -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 + +#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; +} Index: cfe/trunk/test/Misc/warn-in-system-macro-def.c.inc =================================================================== --- cfe/trunk/test/Misc/warn-in-system-macro-def.c.inc +++ cfe/trunk/test/Misc/warn-in-system-macro-def.c.inc @@ -0,0 +1,4 @@ +extern int __isnanf(float f); +extern int __isnan(double f); +extern int __isnanl(long double f); +#define ISNAN isnan