zahiraam added a comment.

In D146148#4224862 <https://reviews.llvm.org/D146148#4224862>, @rjmccall wrote:

> In D146148#4224094 <https://reviews.llvm.org/D146148#4224094>, @aaron.ballman 
> wrote:
>
>> In D146148#4222306 <https://reviews.llvm.org/D146148#4222306>, @zahiraam 
>> wrote:
>>
>>> In D146148#4221651 <https://reviews.llvm.org/D146148#4221651>, @rjmccall 
>>> wrote:
>>>
>>>> Zahira, this is what I was asking you when I asked whether modifying the 
>>>> math.h header was acceptable: whether you were prepared to accept that the 
>>>> warning would only fire on system math.h headers that we'd modified, or 
>>>> whether you cared about making it work with non-cooperative headers.  I 
>>>> wasn't asking if you were willing to change the test code.
>>>
>>> Okay sorry about the confusion. I think the diagnostic should fire when the 
>>> user is including system's math.h and using float_t inside a scope 
>>> cotaining a #pragma clang fp eval-method. 
>>> I am not sure what you mean by "cooperative headers"?
>>
>> Ones that know about the special marking and use it (cooperative) or ones 
>> that don't use the special marking (uncooperative). My intuition is that 
>> we'll want this to work with any math.h because the problem still exists if 
>> you use an older C standard library release with a newer Clang.
>
> Right.  It's not a great solution for standard stuff like this.
>
>>>> - We add a math.h compiler header that `#include_next`s the system math.h 
>>>> and then adds the attribute.  I believe you can just add an attribute to a 
>>>> typedef retroactively with something like `typedef float_t float_t 
>>>> __attribute__((whatever))`.
>>>
>>> So when a user writes:
>>>
>>>   #include <math.h>
>>>    int foo()
>>>    {
>>>       #pragma clang fp eval_method(source)
>>>      return sizeof(float_t);
>>>    }
>>>
>>> It would be as though the user wrote:
>>>
>>>   #include "math.h"
>>>   int foo()
>>>   {
>>>      #pragma clang fp eval_method(source)
>>>     return sizeof(float_t);
>>>   }
>>>
>>> where the content of this new math header being:
>>>
>>>   #include_next <math.h>
>>>   typedef float_t float_t __attribute__((whatever));
>>>   typedef double_t double_t __attribute__((whatever));
>>
>> Correct.
>
> Right.  To be clear, this is a general thing that we already do to a bunch of 
> other headers.  It doesn't require any special handling, the compiler's 
> include directory is just the first entry on the search list for system 
> headers.
>
>>>> - We do checks on every typedef declaration.  There's a builtin-identifier 
>>>> trick that we do with library functions that we should be able to 
>>>> generalize to typedefs, so you wouldn't need to actually do string 
>>>> comparisons, you'd just check whether the `IdentifierInfo*` was storing a 
>>>> special ID.  We'd set that up in `initializeBuiltins` at the start of the 
>>>> translation unit, so the overhead would just be that we'd create two extra 
>>>> `IdentifierInfo*`s in every TU.
>>>>
>>>> The builtin ID logic is currently specific to builtin *functions*, and I 
>>>> don't think we'd want to hack typedef names into that.  But the same 
>>>> storage in `IdentifierInfo*` is also used for identifying the ObjC 
>>>> context-sensitive keywords, by just offsetting the builtin IDs by the 
>>>> NUM_OBJC_KEYWORD.  You should be able to generalize that by also 
>>>> introducing a concept of a builtin *type* name, so that e.g. IDs in 
>>>> [0,NUM_OBJC_KEYWORDS) are ObjCKeywordKinds, IDs in [NUM_OBJC_KEYWORDS, 
>>>> NUM_OBJC_KEYWORDS+NUM_BUILTIN_TYPES) are BuiltinTypeKinds (when you 
>>>> subtract NUM_OBJC_KEYWORDS), and IDs in 
>>>> [NUM_OBJC_KEYWORDS+NUM_BUILTIN_TYPES,∞) are builtin function IDs (when you 
>>>> subtract NUM_OBJC_KEYWORDS+NUM_BUILTIN_TYPES).
>>>
>>> Need to look at this more closely to understand what you are suggesting.
>>
>> Basically, he's saying that instead of doing a string comparison against the 
>> name of the typedef, we can ask the typedef for its `IdentifierInfo *` for 
>> the name and do a pointer comparison against an `IdentiferInfo *` that's 
>> cached.
>
> That's a trick we could do, but I'm actually suggesting a step better than 
> that.  The way we handle builtin functions is that we have bits in the 
> `IdentifierInfo` structure saying that the identifier is a builtin name.  
> Those bits are generally ignored except by a few places in Sema that check 
> for them during lookup.  We eagerly create those identifiers and set those 
> bits at the start of the TU.  We could do the same trick for these names, so 
> that when we're declaring a typedef at global scope we just check whether the 
> name is special and trigger some special processing only if so.  It would add 
> a very, very small overhead to processing every typedef declaration, 
> comparable to the overhead we add to processing every function declaration in 
> order to support the declaration of "builtin" library functions.
>
>>> @rjmccall do you have a preference for any one of these solutions? 
>>> @aaron.ballman ?
>>> Thanks.
>>
>> My slight preference is to modify math.h, but I'd also be okay with doing 
>> the pointer comparison trick. I think there are less includes of math.h than 
>> there are typedefs in a TU, so adding a tiny bit of compile time overhead 
>> when including math.h seems to be a better tradeoff.
>
> Yes, adding a math.h to the compiler header seems like the cleanest thing if 
> it doesn't cause integration headaches.  The redeclaration thing would be a 
> problem if there are math.h's that don't declare these typedefs, for example 
> (if there isn't a way to check for that).

@rjmccall, @aaron.ballman and I looked over various math header files to see 
when float_t/double_t started. It looks like it started with C99 but is allowed 
with C89 with MS for example.

In glibc the typedefs are guarded with an #ifdef __USE_ISOC99__.

MS:

  #if defined _M_IX86 && _M_IX86_FP < 2 && !defined _M_FP_FAST
     typedef long double float_t;
     typedef long double double_t;
  #else
     typedef float  float_t;
     typedef double double_t;
  #endif

It's not guarded with the version of the standard. So, including math.h even 
with std=c89 would have a float_t/double_t.

MacOS, the definition of float_t is not guarded either. We would have the same 
issue than with MS.

  /*  Define float_t and double_t per C standard, ISO/IEC 9899:2011 7.12 2,     
  
      taking advantage of GCC's __FLT_EVAL_METHOD__ (which a compiler may       
  
      define anytime and GCC does) that shadows FLT_EVAL_METHOD (which a        
  
      compiler must define only in float.h).                                    
*\
  /
  #if __FLT_EVAL_METHOD__ == 0
      typedef float float_t;
      typedef double double_t;
  #elif __FLT_EVAL_METHOD__ == 1
      typedef double float_t;
      typedef double double_t;
  #elif __FLT_EVAL_METHOD__ == 2 || __FLT_EVAL_METHOD__ == -1

It looks like we have an array of choices that might make the header method a 
bit uncontrollable.
So, if you all agree I will start looking at the identifier solution that you 
are proposing above. 
Thanks.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D146148/new/

https://reviews.llvm.org/D146148

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D146148: Float... Zahira Ammarguellat via Phabricator via cfe-commits

Reply via email to