On 18.01.2012, at 00:34, Richard Smith wrote:
> On Tue, January 17, 2012 22:49, Sebastian Redl wrote:
>> Author: cornedbee
>> Date: Tue Jan 17 16:49:33 2012
>> New Revision: 148348
>>
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=148348&view=rev
>> Log:
>> Add Sema::isStdInitializerList, which will be necessary for the upcoming
>> operations.
>>
>> Modified:
>> cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/Sema.cpp
>> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>>
>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=14
>> 8348&r1=148347&r2=148348&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jan 17 16:49:33 2012
>> @@ -5767,6 +5767,59 @@
>> return getStdNamespace(); }
>>
>>
>> +bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
>> + assert(getLangOptions().CPlusPlus &&
>> + "Looking for std::initializer_list outside of C++.");
>> +
>> + // We're looking for implicit instantiations of
>> + // template <typename E> class std::initializer_list.
>> +
>> + if (!StdNamespace) // If we haven't seen namespace std yet, this can't be
>> it. + return false;
>> +
>> + const RecordType *RT = Ty->getAs<RecordType>();
>> + if (!RT)
>> + return false;
>> +
>> + ClassTemplateSpecializationDecl *Specialization =
>> + dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
>> + if (!Specialization)
>> + return false;
>> +
>> + if (Specialization->getSpecializationKind() != TSK_ImplicitInstantiation)
>> + return false;
>> +
>> + ClassTemplateDecl *Template = Specialization->getSpecializedTemplate();
>
> It's not clear how we should behave if this isn't a specialization of the
> primary template -- [namespace.std]p1 seems to allow user-specialization of
> std::initializer_list, though that seems unimplementable in general.
I don't think we can do anything reasonable in such a case, so I haven't made
any decision, just wrote the code that was easiest to write.
Option: disallow specialization. That would probably be the most reasonable
approach, all things considered.
Option: allow specialization, but don't give special treatment to
specializations of std::initializer_list (i.e. treat them as normal types).
That's unintuitive, though.
Option: allow specialization and still give special treatment. As you said,
unimplementable.
I'm still somewhat worried about the lack of specification on initializer_list
in general. As far as I can tell, the common C++ ABI doesn't specify the layout
or at least the constructor signature of initializer_list. This is a problem
for codegen. Do we use a constructor of initializer_list? If so, which one?
(E*, size_t), as in libstdc++ and libc++? (E*, E*) as in MSVC's stdlib?
template <size_t N> (E &[N]), as it would be perfectly valid to have in some
stdlib? Do we just look for these constructors and use the first we find? Or do
we just initialize the initializer_list object in-place? Again, what's the
layout? Pointer+size or pointer+pointer?
Also, I believe the specification of the lifetime of the backing array to be
highly defective. [dcl.init.list] says:
"Otherwise, if T is a specialization of std::initializer_list<E>, an
initializer_list object is constructed as described below and used to
initialize the object according to the rules for initialization of an object
from a class of the same type."
Note that it says that an object is constructed and then basically copied to
the actual object. Below, it says:
"The lifetime of the array is the same as that of the initializer_list object."
So if a temporary is constructed, wouldn't the lifetime of the array be that of
the temporary?
The example contradicts this, of course, since that would be stupid, but if the
lifetime of the array is the same as that of the actual initializer_list
object, then how do you implement this?
auto listptr = new std::initializer_list<int>{1, 2, 3, 4, 5};
Or for that matter, since it's equivalent:
auto listptr = new auto{1, 2, 3, 4, 5};
>
>> +
>> + if (!StdInitializerList) {
>> + // Haven't recognized std::initializer_list yet, maybe this is it.
>> + CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
>> + if (TemplateClass->getIdentifier() !=
>> + &PP.getIdentifierTable().get("initializer_list") ||
>> + !TemplateClass->getDeclContext()->Equals(getStdNamespace()))
>
> initializer_list might be inside an inline namespace within std (and I believe
> it is, in libc++). getStdNamespace()->InEnclosingNamespaceSetOf(your
> namespace) should handle this, IIRC.
Done. Although IMO initializer_list should be part of the ABI library and thus
unversioned.
>
>> + return false;
>> + // This is a template called std::initializer_list, but is it the right
>> + // template?
>> + TemplateParameterList *Params = Template->getTemplateParameters();
>> + if (Params->size() != 1)
>> + return false;
>
> Minor nit: a standard library implementation is permitted to give
> initializer_list additional defaulted template parameters.
Done.
And the comment typo from the other commit as well. Thanks.
Sebastian
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits