#pragma diagnostic ignored and template code

Hi,

consider the trivial source code

==== warning.cpp ====

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"

unsigned foo(unsigned x) {
  if (x < 0) return -x;
  return x;
}

#pragma clang diagnostic pop

==== main.cpp ====

#include "warning.hpp"
#include <iostream>

int main() {
  std::cout << foo(1u) << std::endl;
  return 0;
}

I cat and then pasted the wrong code, sorry!

Hi,

consider the trivial source code

==== warning.hpp ====

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"

template <class T>
T foo(T x) {
  if (x < T(0)) return -x;
  return x;
}

#pragma clang diagnostic pop

Hi,

consider the trivial source code

==== warning.cpp ====

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"

unsigned foo(unsigned x) {
if (x < 0) return -x;
return x;
}

#pragma clang diagnostic pop

...

Is that the intended behaviour?

No, it's a bug. A similar problem occurs with inline methods in classes:

class foo {
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wtautological-compare"

  void bar() {
    ...
  }

  #pragma .. pop
};

This is certainly a bug, but it's not trivial to fix.

-Chris

FWIW, the fix would require us to keep track of the source ranges covering each push/pop. Then, when determining whether to suppress a diagnostic during template instantiation/inline member processing/etc., we would perform a binary search in those source ranges to determine the active pragmas, diagnostic flags, etc.

  - Doug

How does this effect similiar pragmas, like align? For example:

#pragma pack(push,1)

unsigned foo(unsigned x) {
if (x < 0) return -x;
return x;
}

#pragma pack(pop)

If that works correctly it seems like we could use the same
infrastructure for storing the alignment info during template
instantiation. If it doesn't work, then it would probably make some
sense to figure out how to solve them both generically, since not
honoring the alignment info could be a pretty serious issue for some
codebases.

Also, is there any chance this could be worked around by using
_Pragma()? That would be the solution in a C macro, but I am unsure
what the semantics of _Pragma() with respect to template instantiation
are.

Louis

It is completely unrelated, it uses different infrastructure.

-Chris

Hi,

consider the trivial source code

==== warning.cpp ====

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"

unsigned foo(unsigned x) {
if (x < 0) return -x;
return x;
}

#pragma clang diagnostic pop

...

Is that the intended behaviour?

No, it's a bug. A similar problem occurs with inline methods in classes:

class foo {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"

void bar() {
   ...
}

#pragma .. pop
};

This is certainly a bug, but it's not trivial to fix.

FWIW, the fix would require us to keep track of the source ranges covering each push/pop. Then, when determining whether to suppress a diagnostic during template instantiation/inline member processing/etc., we would perform a binary search in those source ranges to determine the active pragmas, diagnostic flags, etc.

How does this effect similiar pragmas, like align? For example:

#pragma pack(push,1)

unsigned foo(unsigned x) {
if (x < 0) return -x;
return x;
}

#pragma pack(pop)

If that works correctly it seems like we could use the same
infrastructure for storing the alignment info during template
instantiation. If it doesn't work, then it would probably make some
sense to figure out how to solve them both generically, since not
honoring the alignment info could be a pretty serious issue for some
codebases.

It's different infrastructure, but both would need similar updates; perhaps a generic infrastructure could work here.

Also, is there any chance this could be worked around by using
_Pragma()? That would be the solution in a C macro, but I am unsure
what the semantics of _Pragma() with respect to template instantiation
are.

_Pragma() won't help at all. Use attributes instead.

  - Doug

No, it's a bug.

In which case,

http://llvm.org/bugs/show_bug.cgi?id=8143

Luc