Index: vendor/clang/dist/docs/AutomaticReferenceCounting.rst =================================================================== --- vendor/clang/dist/docs/AutomaticReferenceCounting.rst (revision 313882) +++ vendor/clang/dist/docs/AutomaticReferenceCounting.rst (revision 313883) @@ -1,2291 +1,2288 @@ .. FIXME: move to the stylesheet or Sphinx plugin .. raw:: html .. role:: arc-term .. role:: revision .. role:: when-revised ============================================== Objective-C Automatic Reference Counting (ARC) ============================================== .. contents:: :local: .. _arc.meta: About this document =================== .. _arc.meta.purpose: Purpose ------- The first and primary purpose of this document is to serve as a complete technical specification of Automatic Reference Counting. Given a core Objective-C compiler and runtime, it should be possible to write a compiler and runtime which implements these new semantics. The secondary purpose is to act as a rationale for why ARC was designed in this way. This should remain tightly focused on the technical design and should not stray into marketing speculation. .. _arc.meta.background: Background ---------- This document assumes a basic familiarity with C. :arc-term:`Blocks` are a C language extension for creating anonymous functions. Users interact with and transfer block objects using :arc-term:`block pointers`, which are represented like a normal pointer. A block may capture values from local variables; when this occurs, memory must be dynamically allocated. The initial allocation is done on the stack, but the runtime provides a ``Block_copy`` function which, given a block pointer, either copies the underlying block object to the heap, setting its reference count to 1 and returning the new block pointer, or (if the block object is already on the heap) increases its reference count by 1. The paired function is ``Block_release``, which decreases the reference count by 1 and destroys the object if the count reaches zero and is on the heap. Objective-C is a set of language extensions, significant enough to be considered a different language. It is a strict superset of C. The extensions can also be imposed on C++, producing a language called Objective-C++. The primary feature is a single-inheritance object system; we briefly describe the modern dialect. Objective-C defines a new type kind, collectively called the :arc-term:`object pointer types`. This kind has two notable builtin members, ``id`` and ``Class``; ``id`` is the final supertype of all object pointers. The validity of conversions between object pointer types is not checked at runtime. Users may define :arc-term:`classes`; each class is a type, and the pointer to that type is an object pointer type. A class may have a superclass; its pointer type is a subtype of its superclass's pointer type. A class has a set of :arc-term:`ivars`, fields which appear on all instances of that class. For every class *T* there's an associated metaclass; it has no fields, its superclass is the metaclass of *T*'s superclass, and its metaclass is a global class. Every class has a global object whose class is the class's metaclass; metaclasses have no associated type, so pointers to this object have type ``Class``. A class declaration (``@interface``) declares a set of :arc-term:`methods`. A method has a return type, a list of argument types, and a :arc-term:`selector`: a name like ``foo:bar:baz:``, where the number of colons corresponds to the number of formal arguments. A method may be an instance method, in which case it can be invoked on objects of the class, or a class method, in which case it can be invoked on objects of the metaclass. A method may be invoked by providing an object (called the :arc-term:`receiver`) and a list of formal arguments interspersed with the selector, like so: .. code-block:: objc [receiver foo: fooArg bar: barArg baz: bazArg] This looks in the dynamic class of the receiver for a method with this name, then in that class's superclass, etc., until it finds something it can execute. The receiver "expression" may also be the name of a class, in which case the actual receiver is the class object for that class, or (within method definitions) it may be ``super``, in which case the lookup algorithm starts with the static superclass instead of the dynamic class. The actual methods dynamically found in a class are not those declared in the ``@interface``, but those defined in a separate ``@implementation`` declaration; however, when compiling a call, typechecking is done based on the methods declared in the ``@interface``. Method declarations may also be grouped into :arc-term:`protocols`, which are not inherently associated with any class, but which classes may claim to follow. Object pointer types may be qualified with additional protocols that the object is known to support. :arc-term:`Class extensions` are collections of ivars and methods, designed to allow a class's ``@interface`` to be split across multiple files; however, there is still a primary implementation file which must see the ``@interface``\ s of all class extensions. :arc-term:`Categories` allow methods (but not ivars) to be declared *post hoc* on an arbitrary class; the methods in the category's ``@implementation`` will be dynamically added to that class's method tables which the category is loaded at runtime, replacing those methods in case of a collision. In the standard environment, objects are allocated on the heap, and their lifetime is manually managed using a reference count. This is done using two instance methods which all classes are expected to implement: ``retain`` increases the object's reference count by 1, whereas ``release`` decreases it by 1 and calls the instance method ``dealloc`` if the count reaches 0. To simplify certain operations, there is also an :arc-term:`autorelease pool`, a thread-local list of objects to call ``release`` on later; an object can be added to this pool by calling ``autorelease`` on it. Block pointers may be converted to type ``id``; block objects are laid out in a way that makes them compatible with Objective-C objects. There is a builtin class that all block objects are considered to be objects of; this class implements ``retain`` by adjusting the reference count, not by calling ``Block_copy``. .. _arc.meta.evolution: Evolution --------- ARC is under continual evolution, and this document must be updated as the language progresses. If a change increases the expressiveness of the language, for example by lifting a restriction or by adding new syntax, the change will be annotated with a revision marker, like so: ARC applies to Objective-C pointer types, block pointer types, and :when-revised:`[beginning Apple 8.0, LLVM 3.8]` :revision:`BPTRs declared within` ``extern "BCPL"`` blocks. For now, it is sensible to version this document by the releases of its sole implementation (and its host project), clang. "LLVM X.Y" refers to an open-source release of clang from the LLVM project. "Apple X.Y" refers to an Apple-provided release of the Apple LLVM Compiler. Other organizations that prepare their own, separately-versioned clang releases and wish to maintain similar information in this document should send requests to cfe-dev. If a change decreases the expressiveness of the language, for example by imposing a new restriction, this should be taken as an oversight in the original specification and something to be avoided in all versions. Such changes are generally to be avoided. .. _arc.general: General ======= Automatic Reference Counting implements automatic memory management for Objective-C objects and blocks, freeing the programmer from the need to explicitly insert retains and releases. It does not provide a cycle collector; users must explicitly manage the lifetime of their objects, breaking cycles manually or with weak or unsafe references. ARC may be explicitly enabled with the compiler flag ``-fobjc-arc``. It may also be explicitly disabled with the compiler flag ``-fno-objc-arc``. The last of these two flags appearing on the compile line "wins". If ARC is enabled, ``__has_feature(objc_arc)`` will expand to 1 in the preprocessor. For more information about ``__has_feature``, see the :ref:`language extensions ` document. .. _arc.objects: Retainable object pointers ========================== This section describes retainable object pointers, their basic operations, and the restrictions imposed on their use under ARC. Note in particular that it covers the rules for pointer *values* (patterns of bits indicating the location of a pointed-to object), not pointer *objects* (locations in memory which store pointer values). The rules for objects are covered in the next section. A :arc-term:`retainable object pointer` (or "retainable pointer") is a value of a :arc-term:`retainable object pointer type` ("retainable type"). There are three kinds of retainable object pointer types: * block pointers (formed by applying the caret (``^``) declarator sigil to a function type) * Objective-C object pointers (``id``, ``Class``, ``NSFoo*``, etc.) * typedefs marked with ``__attribute__((NSObject))`` Other pointer types, such as ``int*`` and ``CFStringRef``, are not subject to ARC's semantics and restrictions. .. admonition:: Rationale We are not at liberty to require all code to be recompiled with ARC; therefore, ARC must interoperate with Objective-C code which manages retains and releases manually. In general, there are three requirements in order for a compiler-supported reference-count system to provide reliable interoperation: * The type system must reliably identify which objects are to be managed. An ``int*`` might be a pointer to a ``malloc``'ed array, or it might be an interior pointer to such an array, or it might point to some field or local variable. In contrast, values of the retainable object pointer types are never interior. * The type system must reliably indicate how to manage objects of a type. This usually means that the type must imply a procedure for incrementing and decrementing retain counts. Supporting single-ownership objects requires a lot more explicit mediation in the language. * There must be reliable conventions for whether and when "ownership" is passed between caller and callee, for both arguments and return values. Objective-C methods follow such a convention very reliably, at least for system libraries on Mac OS X, and functions always pass objects at +0. The C-based APIs for Core Foundation objects, on the other hand, have much more varied transfer semantics. The use of ``__attribute__((NSObject))`` typedefs is not recommended. If it's absolutely necessary to use this attribute, be very explicit about using the typedef, and do not assume that it will be preserved by language features like ``__typeof`` and C++ template argument substitution. .. admonition:: Rationale Any compiler operation which incidentally strips type "sugar" from a type will yield a type without the attribute, which may result in unexpected behavior. .. _arc.objects.retains: Retain count semantics ---------------------- A retainable object pointer is either a :arc-term:`null pointer` or a pointer to a valid object. Furthermore, if it has block pointer type and is not ``null`` then it must actually be a pointer to a block object, and if it has ``Class`` type (possibly protocol-qualified) then it must actually be a pointer to a class object. Otherwise ARC does not enforce the Objective-C type system as long as the implementing methods follow the signature of the static type. It is undefined behavior if ARC is exposed to an invalid pointer. For ARC's purposes, a valid object is one with "well-behaved" retaining operations. Specifically, the object must be laid out such that the Objective-C message send machinery can successfully send it the following messages: * ``retain``, taking no arguments and returning a pointer to the object. * ``release``, taking no arguments and returning ``void``. * ``autorelease``, taking no arguments and returning a pointer to the object. The behavior of these methods is constrained in the following ways. The term :arc-term:`high-level semantics` is an intentionally vague term; the intent is that programmers must implement these methods in a way such that the compiler, modifying code in ways it deems safe according to these constraints, will not violate their requirements. For example, if the user puts logging statements in ``retain``, they should not be surprised if those statements are executed more or less often depending on optimization settings. These constraints are not exhaustive of the optimization opportunities: values held in local variables are subject to additional restrictions, described later in this document. It is undefined behavior if a computation history featuring a send of ``retain`` followed by a send of ``release`` to the same object, with no intervening ``release`` on that object, is not equivalent under the high-level semantics to a computation history in which these sends are removed. Note that this implies that these methods may not raise exceptions. It is undefined behavior if a computation history features any use whatsoever of an object following the completion of a send of ``release`` that is not preceded by a send of ``retain`` to the same object. The behavior of ``autorelease`` must be equivalent to sending ``release`` when one of the autorelease pools currently in scope is popped. It may not throw an exception. When the semantics call for performing one of these operations on a retainable object pointer, if that pointer is ``null`` then the effect is a no-op. All of the semantics described in this document are subject to additional :ref:`optimization rules ` which permit the removal or optimization of operations based on local knowledge of data flow. The semantics describe the high-level behaviors that the compiler implements, not an exact sequence of operations that a program will be compiled into. .. _arc.objects.operands: Retainable object pointers as operands and arguments ---------------------------------------------------- In general, ARC does not perform retain or release operations when simply using a retainable object pointer as an operand within an expression. This includes: * loading a retainable pointer from an object with non-weak :ref:`ownership `, * passing a retainable pointer as an argument to a function or method, and * receiving a retainable pointer as the result of a function or method call. .. admonition:: Rationale While this might seem uncontroversial, it is actually unsafe when multiple expressions are evaluated in "parallel", as with binary operators and calls, because (for example) one expression might load from an object while another writes to it. However, C and C++ already call this undefined behavior because the evaluations are unsequenced, and ARC simply exploits that here to avoid needing to retain arguments across a large number of calls. The remainder of this section describes exceptions to these rules, how those exceptions are detected, and what those exceptions imply semantically. .. _arc.objects.operands.consumed: Consumed parameters ^^^^^^^^^^^^^^^^^^^ A function or method parameter of retainable object pointer type may be marked as :arc-term:`consumed`, signifying that the callee expects to take ownership of a +1 retain count. This is done by adding the ``ns_consumed`` attribute to the parameter declaration, like so: .. code-block:: objc void foo(__attribute((ns_consumed)) id x); - (void) foo: (id) __attribute((ns_consumed)) x; This attribute is part of the type of the function or method, not the type of the parameter. It controls only how the argument is passed and received. When passing such an argument, ARC retains the argument prior to making the call. When receiving such an argument, ARC releases the argument at the end of the function, subject to the usual optimizations for local values. .. admonition:: Rationale This formalizes direct transfers of ownership from a caller to a callee. The most common scenario here is passing the ``self`` parameter to ``init``, but it is useful to generalize. Typically, local optimization will remove any extra retains and releases: on the caller side the retain will be merged with a +1 source, and on the callee side the release will be rolled into the initialization of the parameter. The implicit ``self`` parameter of a method may be marked as consumed by adding ``__attribute__((ns_consumes_self))`` to the method declaration. Methods in the ``init`` :ref:`family ` are treated as if they were implicitly marked with this attribute. It is undefined behavior if an Objective-C message send to a method with ``ns_consumed`` parameters (other than self) is made with a null receiver. It is undefined behavior if the method to which an Objective-C message send statically resolves to has a different set of ``ns_consumed`` parameters than the method it dynamically resolves to. It is undefined behavior if a block or function call is made through a static type with a different set of ``ns_consumed`` parameters than the implementation of the called block or function. .. admonition:: Rationale Consumed parameters with null receiver are a guaranteed leak. Mismatches with consumed parameters will cause over-retains or over-releases, depending on the direction. The rule about function calls is really just an application of the existing C/C++ rule about calling functions through an incompatible function type, but it's useful to state it explicitly. .. _arc.object.operands.retained-return-values: Retained return values ^^^^^^^^^^^^^^^^^^^^^^ A function or method which returns a retainable object pointer type may be marked as returning a retained value, signifying that the caller expects to take ownership of a +1 retain count. This is done by adding the ``ns_returns_retained`` attribute to the function or method declaration, like so: .. code-block:: objc id foo(void) __attribute((ns_returns_retained)); - (id) foo __attribute((ns_returns_retained)); This attribute is part of the type of the function or method. When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, before leaving all local scopes. When receiving a return result from such a function or method, ARC releases the value at the end of the full-expression it is contained within, subject to the usual optimizations for local values. .. admonition:: Rationale This formalizes direct transfers of ownership from a callee to a caller. The most common scenario this models is the retained return from ``init``, ``alloc``, ``new``, and ``copy`` methods, but there are other cases in the frameworks. After optimization there are typically no extra retains and releases required. Methods in the ``alloc``, ``copy``, ``init``, ``mutableCopy``, and ``new`` :ref:`families ` are implicitly marked ``__attribute__((ns_returns_retained))``. This may be suppressed by explicitly marking the method ``__attribute__((ns_returns_not_retained))``. It is undefined behavior if the method to which an Objective-C message send statically resolves has different retain semantics on its result from the method it dynamically resolves to. It is undefined behavior if a block or function call is made through a static type with different retain semantics on its result from the implementation of the called block or function. .. admonition:: Rationale Mismatches with returned results will cause over-retains or over-releases, depending on the direction. Again, the rule about function calls is really just an application of the existing C/C++ rule about calling functions through an incompatible function type. .. _arc.objects.operands.unretained-returns: Unretained return values ^^^^^^^^^^^^^^^^^^^^^^^^ A method or function which returns a retainable object type but does not return a retained value must ensure that the object is still valid across the return boundary. When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain while ensuring that the value lives across the call boundary. In the worst case, this may involve an ``autorelease``, but callers must not assume that the value is actually in the autorelease pool. ARC performs no extra mandatory work on the caller side, although it may elect to do something to shorten the lifetime of the returned value. .. admonition:: Rationale It is common in non-ARC code to not return an autoreleased value; therefore the convention does not force either path. It is convenient to not be required to do unnecessary retains and autoreleases; this permits optimizations such as eliding retain/autoreleases when it can be shown that the original pointer will still be valid at the point of return. A method or function may be marked with ``__attribute__((ns_returns_autoreleased))`` to indicate that it returns a pointer which is guaranteed to be valid at least as long as the innermost autorelease pool. There are no additional semantics enforced in the definition of such a method; it merely enables optimizations in callers. .. _arc.objects.operands.casts: Bridged casts ^^^^^^^^^^^^^ A :arc-term:`bridged cast` is a C-style cast annotated with one of three keywords: * ``(__bridge T) op`` casts the operand to the destination type ``T``. If ``T`` is a retainable object pointer type, then ``op`` must have a non-retainable pointer type. If ``T`` is a non-retainable pointer type, then ``op`` must have a retainable object pointer type. Otherwise the cast is ill-formed. There is no transfer of ownership, and ARC inserts no retain operations. * ``(__bridge_retained T) op`` casts the operand, which must have retainable object pointer type, to the destination type, which must be a non-retainable pointer type. ARC retains the value, subject to the usual optimizations on local values, and the recipient is responsible for balancing that +1. * ``(__bridge_transfer T) op`` casts the operand, which must have non-retainable pointer type, to the destination type, which must be a retainable object pointer type. ARC will release the value at the end of the enclosing full-expression, subject to the usual optimizations on local values. These casts are required in order to transfer objects in and out of ARC control; see the rationale in the section on :ref:`conversion of retainable object pointers `. Using a ``__bridge_retained`` or ``__bridge_transfer`` cast purely to convince ARC to emit an unbalanced retain or release, respectively, is poor form. .. _arc.objects.restrictions: Restrictions ------------ .. _arc.objects.restrictions.conversion: Conversion of retainable object pointers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In general, a program which attempts to implicitly or explicitly convert a value of retainable object pointer type to any non-retainable type, or vice-versa, is ill-formed. For example, an Objective-C object pointer shall not be converted to ``void*``. As an exception, cast to ``intptr_t`` is allowed because such casts are not transferring ownership. The :ref:`bridged casts ` may be used to perform these conversions where necessary. .. admonition:: Rationale We cannot ensure the correct management of the lifetime of objects if they may be freely passed around as unmanaged types. The bridged casts are provided so that the programmer may explicitly describe whether the cast transfers control into or out of ARC. However, the following exceptions apply. .. _arc.objects.restrictions.conversion.with.known.semantics: Conversion to retainable object pointer type of expressions with known semantics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :when-revised:`[beginning Apple 4.0, LLVM 3.1]` :revision:`These exceptions have been greatly expanded; they previously applied only to a much-reduced subset which is difficult to categorize but which included null pointers, message sends (under the given rules), and the various global constants.` An unbridged conversion to a retainable object pointer type from a type other than a retainable object pointer type is ill-formed, as discussed above, unless the operand of the cast has a syntactic form which is known retained, known unretained, or known retain-agnostic. An expression is :arc-term:`known retain-agnostic` if it is: * an Objective-C string literal, * a load from a ``const`` system global variable of :ref:`C retainable pointer type `, or * a null pointer constant. An expression is :arc-term:`known unretained` if it is an rvalue of :ref:`C retainable pointer type ` and it is: * a direct call to a function, and either that function has the ``cf_returns_not_retained`` attribute or it is an :ref:`audited ` function that does not have the ``cf_returns_retained`` attribute and does not follow the create/copy naming convention, * a message send, and the declared method either has the ``cf_returns_not_retained`` attribute or it has neither the ``cf_returns_retained`` attribute nor a :ref:`selector family ` that implies a retained result, or * :when-revised:`[beginning LLVM 3.6]` :revision:`a load from a` ``const`` :revision:`non-system global variable.` An expression is :arc-term:`known retained` if it is an rvalue of :ref:`C retainable pointer type ` and it is: * a message send, and the declared method either has the ``cf_returns_retained`` attribute, or it does not have the ``cf_returns_not_retained`` attribute but it does have a :ref:`selector family ` that implies a retained result. Furthermore: * a comma expression is classified according to its right-hand side, * a statement expression is classified according to its result expression, if it has one, * an lvalue-to-rvalue conversion applied to an Objective-C property lvalue is classified according to the underlying message send, and * a conditional operator is classified according to its second and third operands, if they agree in classification, or else the other if one is known retain-agnostic. If the cast operand is known retained, the conversion is treated as a ``__bridge_transfer`` cast. If the cast operand is known unretained or known retain-agnostic, the conversion is treated as a ``__bridge`` cast. .. admonition:: Rationale Bridging casts are annoying. Absent the ability to completely automate the management of CF objects, however, we are left with relatively poor attempts to reduce the need for a glut of explicit bridges. Hence these rules. We've so far consciously refrained from implicitly turning retained CF results from function calls into ``__bridge_transfer`` casts. The worry is that some code patterns --- for example, creating a CF value, assigning it to an ObjC-typed local, and then calling ``CFRelease`` when done --- are a bit too likely to be accidentally accepted, leading to mysterious behavior. For loads from ``const`` global variables of :ref:`C retainable pointer type `, it is reasonable to assume that global system constants were initialitzed with true constants (e.g. string literals), but user constants might have been initialized with something dynamically allocated, using a global initializer. .. _arc.objects.restrictions.conversion-exception-contextual: Conversion from retainable object pointer type in certain contexts ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :when-revised:`[beginning Apple 4.0, LLVM 3.1]` If an expression of retainable object pointer type is explicitly cast to a :ref:`C retainable pointer type `, the program is ill-formed as discussed above unless the result is immediately used: * to initialize a parameter in an Objective-C message send where the parameter is not marked with the ``cf_consumed`` attribute, or * to initialize a parameter in a direct call to an :ref:`audited ` function where the parameter is not marked with the ``cf_consumed`` attribute. .. admonition:: Rationale Consumed parameters are left out because ARC would naturally balance them with a retain, which was judged too treacherous. This is in part because several of the most common consuming functions are in the ``Release`` family, and it would be quite unfortunate for explicit releases to be silently balanced out in this way. .. _arc.ownership: Ownership qualification ======================= This section describes the behavior of *objects* of retainable object pointer type; that is, locations in memory which store retainable object pointers. A type is a :arc-term:`retainable object owner type` if it is a retainable object pointer type or an array type whose element type is a retainable object owner type. An :arc-term:`ownership qualifier` is a type qualifier which applies only to retainable object owner types. An array type is ownership-qualified according to its element type, and adding an ownership qualifier to an array type so qualifies its element type. A program is ill-formed if it attempts to apply an ownership qualifier to a type which is already ownership-qualified, even if it is the same qualifier. There is a single exception to this rule: an ownership qualifier may be applied to a substituted template type parameter, which overrides the ownership qualifier provided by the template argument. When forming a function type, the result type is adjusted so that any top-level ownership qualifier is deleted. Except as described under the :ref:`inference rules `, a program is ill-formed if it attempts to form a pointer or reference type to a retainable object owner type which lacks an ownership qualifier. .. admonition:: Rationale These rules, together with the inference rules, ensure that all objects and lvalues of retainable object pointer type have an ownership qualifier. The ability to override an ownership qualifier during template substitution is required to counteract the :ref:`inference of __strong for template type arguments `. Ownership qualifiers on return types are dropped because they serve no purpose there except to cause spurious problems with overloading and templates. There are four ownership qualifiers: * ``__autoreleasing`` * ``__strong`` * ``__unsafe_unretained`` * ``__weak`` A type is :arc-term:`nontrivially ownership-qualified` if it is qualified with ``__autoreleasing``, ``__strong``, or ``__weak``. .. _arc.ownership.spelling: Spelling -------- The names of the ownership qualifiers are reserved for the implementation. A program may not assume that they are or are not implemented with macros, or what those macros expand to. An ownership qualifier may be written anywhere that any other type qualifier may be written. If an ownership qualifier appears in the *declaration-specifiers*, the following rules apply: * if the type specifier is a retainable object owner type, the qualifier initially applies to that type; * otherwise, if the outermost non-array declarator is a pointer or block pointer declarator, the qualifier initially applies to that type; * otherwise the program is ill-formed. * If the qualifier is so applied at a position in the declaration where the next-innermost declarator is a function declarator, and there is an block declarator within that function declarator, then the qualifier applies instead to that block declarator and this rule is considered afresh beginning from the new position. If an ownership qualifier appears on the declarator name, or on the declared object, it is applied to the innermost pointer or block-pointer type. If an ownership qualifier appears anywhere else in a declarator, it applies to the type there. .. admonition:: Rationale Ownership qualifiers are like ``const`` and ``volatile`` in the sense that they may sensibly apply at multiple distinct positions within a declarator. However, unlike those qualifiers, there are many situations where they are not meaningful, and so we make an effort to "move" the qualifier to a place where it will be meaningful. The general goal is to allow the programmer to write, say, ``__strong`` before the entire declaration and have it apply in the leftmost sensible place. .. _arc.ownership.spelling.property: Property declarations ^^^^^^^^^^^^^^^^^^^^^ A property of retainable object pointer type may have ownership. If the property's type is ownership-qualified, then the property has that ownership. If the property has one of the following modifiers, then the property has the corresponding ownership. A property is ill-formed if it has conflicting sources of ownership, or if it has redundant ownership modifiers, or if it has ``__autoreleasing`` ownership. * ``assign`` implies ``__unsafe_unretained`` ownership. * ``copy`` implies ``__strong`` ownership, as well as the usual behavior of copy semantics on the setter. * ``retain`` implies ``__strong`` ownership. * ``strong`` implies ``__strong`` ownership. * ``unsafe_unretained`` implies ``__unsafe_unretained`` ownership. * ``weak`` implies ``__weak`` ownership. With the exception of ``weak``, these modifiers are available in non-ARC modes. A property's specified ownership is preserved in its metadata, but otherwise the meaning is purely conventional unless the property is synthesized. If a property is synthesized, then the :arc-term:`associated instance variable` is the instance variable which is named, possibly implicitly, by the ``@synthesize`` declaration. If the associated instance variable already exists, then its ownership qualification must equal the ownership of the property; otherwise, the instance variable is created with that ownership qualification. A property of retainable object pointer type which is synthesized without a source of ownership has the ownership of its associated instance variable, if it already exists; otherwise, :when-revised:`[beginning Apple 3.1, LLVM 3.1]` :revision:`its ownership is implicitly` ``strong``. Prior to this revision, it was ill-formed to synthesize such a property. .. admonition:: Rationale Using ``strong`` by default is safe and consistent with the generic ARC rule about :ref:`inferring ownership `. It is, unfortunately, inconsistent with the non-ARC rule which states that such properties are implicitly ``assign``. However, that rule is clearly untenable in ARC, since it leads to default-unsafe code. The main merit to banning the properties is to avoid confusion with non-ARC practice, which did not ultimately strike us as sufficient to justify requiring extra syntax and (more importantly) forcing novices to understand ownership rules just to declare a property when the default is so reasonable. Changing the rule away from non-ARC practice was acceptable because we had conservatively banned the synthesis in order to give ourselves exactly this leeway. Applying ``__attribute__((NSObject))`` to a property not of retainable object pointer type has the same behavior it does outside of ARC: it requires the property type to be some sort of pointer and permits the use of modifiers other than ``assign``. These modifiers only affect the synthesized getter and setter; direct accesses to the ivar (even if synthesized) still have primitive semantics, and the value in the ivar will not be automatically released during deallocation. .. _arc.ownership.semantics: Semantics --------- There are five :arc-term:`managed operations` which may be performed on an object of retainable object pointer type. Each qualifier specifies different semantics for each of these operations. It is still undefined behavior to access an object outside of its lifetime. A load or store with "primitive semantics" has the same semantics as the respective operation would have on an ``void*`` lvalue with the same alignment and non-ownership qualification. :arc-term:`Reading` occurs when performing a lvalue-to-rvalue conversion on an object lvalue. * For ``__weak`` objects, the current pointee is retained and then released at the end of the current full-expression. This must execute atomically with respect to assignments and to the final release of the pointee. * For all other objects, the lvalue is loaded with primitive semantics. :arc-term:`Assignment` occurs when evaluating an assignment operator. The semantics vary based on the qualification: * For ``__strong`` objects, the new pointee is first retained; second, the lvalue is loaded with primitive semantics; third, the new pointee is stored into the lvalue with primitive semantics; and finally, the old pointee is released. This is not performed atomically; external synchronization must be used to make this safe in the face of concurrent loads and stores. * For ``__weak`` objects, the lvalue is updated to point to the new pointee, unless the new pointee is an object currently undergoing deallocation, in which case the lvalue is updated to a null pointer. This must execute atomically with respect to other assignments to the object, to reads from the object, and to the final release of the new pointee. * For ``__unsafe_unretained`` objects, the new pointee is stored into the lvalue using primitive semantics. * For ``__autoreleasing`` objects, the new pointee is retained, autoreleased, and stored into the lvalue using primitive semantics. :arc-term:`Initialization` occurs when an object's lifetime begins, which depends on its storage duration. Initialization proceeds in two stages: #. First, a null pointer is stored into the lvalue using primitive semantics. This step is skipped if the object is ``__unsafe_unretained``. #. Second, if the object has an initializer, that expression is evaluated and then assigned into the object using the usual assignment semantics. :arc-term:`Destruction` occurs when an object's lifetime ends. In all cases it is semantically equivalent to assigning a null pointer to the object, with the proviso that of course the object cannot be legally read after the object's lifetime ends. :arc-term:`Moving` occurs in specific situations where an lvalue is "moved from", meaning that its current pointee will be used but the object may be left in a different (but still valid) state. This arises with ``__block`` variables and rvalue references in C++. For ``__strong`` lvalues, moving is equivalent to loading the lvalue with primitive semantics, writing a null pointer to it with primitive semantics, and then releasing the result of the load at the end of the current full-expression. For all other lvalues, moving is equivalent to reading the object. .. _arc.ownership.restrictions: Restrictions ------------ .. _arc.ownership.restrictions.weak: Weak-unavailable types ^^^^^^^^^^^^^^^^^^^^^^ It is explicitly permitted for Objective-C classes to not support ``__weak`` references. It is undefined behavior to perform an operation with weak assignment semantics with a pointer to an Objective-C object whose class does not support ``__weak`` references. .. admonition:: Rationale Historically, it has been possible for a class to provide its own reference-count implementation by overriding ``retain``, ``release``, etc. However, weak references to an object require coordination with its class's reference-count implementation because, among other things, weak loads and stores must be atomic with respect to the final release. Therefore, existing custom reference-count implementations will generally not support weak references without additional effort. This is unavoidable without breaking binary compatibility. A class may indicate that it does not support weak references by providing the ``objc_arc_weak_reference_unavailable`` attribute on the class's interface declaration. A retainable object pointer type is **weak-unavailable** if is a pointer to an (optionally protocol-qualified) Objective-C class ``T`` where ``T`` or one of its superclasses has the ``objc_arc_weak_reference_unavailable`` attribute. A program is ill-formed if it applies the ``__weak`` ownership qualifier to a weak-unavailable type or if the value operand of a weak assignment operation has a weak-unavailable type. .. _arc.ownership.restrictions.autoreleasing: Storage duration of ``__autoreleasing`` objects ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A program is ill-formed if it declares an ``__autoreleasing`` object of non-automatic storage duration. A program is ill-formed if it captures an ``__autoreleasing`` object in a block or, unless by reference, in a C++11 lambda. .. admonition:: Rationale Autorelease pools are tied to the current thread and scope by their nature. While it is possible to have temporary objects whose instance variables are filled with autoreleased objects, there is no way that ARC can provide any sort of safety guarantee there. It is undefined behavior if a non-null pointer is assigned to an ``__autoreleasing`` object while an autorelease pool is in scope and then that object is read after the autorelease pool's scope is left. .. _arc.ownership.restrictions.conversion.indirect: Conversion of pointers to ownership-qualified types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A program is ill-formed if an expression of type ``T*`` is converted, explicitly or implicitly, to the type ``U*``, where ``T`` and ``U`` have different ownership qualification, unless: * ``T`` is qualified with ``__strong``, ``__autoreleasing``, or ``__unsafe_unretained``, and ``U`` is qualified with both ``const`` and ``__unsafe_unretained``; or * either ``T`` or ``U`` is ``cv void``, where ``cv`` is an optional sequence of non-ownership qualifiers; or * the conversion is requested with a ``reinterpret_cast`` in Objective-C++; or * the conversion is a well-formed :ref:`pass-by-writeback `. The analogous rule applies to ``T&`` and ``U&`` in Objective-C++. .. admonition:: Rationale These rules provide a reasonable level of type-safety for indirect pointers, as long as the underlying memory is not deallocated. The conversion to ``const __unsafe_unretained`` is permitted because the semantics of reads are equivalent across all these ownership semantics, and that's a very useful and common pattern. The interconversion with ``void*`` is useful for allocating memory or otherwise escaping the type system, but use it carefully. ``reinterpret_cast`` is considered to be an obvious enough sign of taking responsibility for any problems. It is undefined behavior to access an ownership-qualified object through an lvalue of a differently-qualified type, except that any non-``__weak`` object may be read through an ``__unsafe_unretained`` lvalue. It is undefined behavior if a managed operation is performed on a ``__strong`` or ``__weak`` object without a guarantee that it contains a primitive zero bit-pattern, or if the storage for such an object is freed or reused without the object being first assigned a null pointer. .. admonition:: Rationale ARC cannot differentiate between an assignment operator which is intended to "initialize" dynamic memory and one which is intended to potentially replace a value. Therefore the object's pointer must be valid before letting ARC at it. Similarly, C and Objective-C do not provide any language hooks for destroying objects held in dynamic memory, so it is the programmer's responsibility to avoid leaks (``__strong`` objects) and consistency errors (``__weak`` objects). These requirements are followed automatically in Objective-C++ when creating objects of retainable object owner type with ``new`` or ``new[]`` and destroying them with ``delete``, ``delete[]``, or a pseudo-destructor expression. Note that arrays of nontrivially-ownership-qualified type are not ABI compatible with non-ARC code because the element type is non-POD: such arrays that are ``new[]``'d in ARC translation units cannot be ``delete[]``'d in non-ARC translation units and vice-versa. .. _arc.ownership.restrictions.pass_by_writeback: Passing to an out parameter by writeback ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If the argument passed to a parameter of type ``T __autoreleasing *`` has type ``U oq *``, where ``oq`` is an ownership qualifier, then the argument is a candidate for :arc-term:`pass-by-writeback`` if: * ``oq`` is ``__strong`` or ``__weak``, and * it would be legal to initialize a ``T __strong *`` with a ``U __strong *``. For purposes of overload resolution, an implicit conversion sequence requiring a pass-by-writeback is always worse than an implicit conversion sequence not requiring a pass-by-writeback. The pass-by-writeback is ill-formed if the argument expression does not have a legal form: * ``&var``, where ``var`` is a scalar variable of automatic storage duration with retainable object pointer type * a conditional expression where the second and third operands are both legal forms * a cast whose operand is a legal form * a null pointer constant .. admonition:: Rationale The restriction in the form of the argument serves two purposes. First, it makes it impossible to pass the address of an array to the argument, which serves to protect against an otherwise serious risk of mis-inferring an "array" argument as an out-parameter. Second, it makes it much less likely that the user will see confusing aliasing problems due to the implementation, below, where their store to the writeback temporary is not immediately seen in the original argument variable. A pass-by-writeback is evaluated as follows: #. The argument is evaluated to yield a pointer ``p`` of type ``U oq *``. #. If ``p`` is a null pointer, then a null pointer is passed as the argument, and no further work is required for the pass-by-writeback. #. Otherwise, a temporary of type ``T __autoreleasing`` is created and initialized to a null pointer. #. If the parameter is not an Objective-C method parameter marked ``out``, then ``*p`` is read, and the result is written into the temporary with primitive semantics. #. The address of the temporary is passed as the argument to the actual call. #. After the call completes, the temporary is loaded with primitive semantics, and that value is assigned into ``*p``. .. admonition:: Rationale This is all admittedly convoluted. In an ideal world, we would see that a local variable is being passed to an out-parameter and retroactively modify its type to be ``__autoreleasing`` rather than ``__strong``. This would be remarkably difficult and not always well-founded under the C type system. However, it was judged unacceptably invasive to require programmers to write ``__autoreleasing`` on all the variables they intend to use for out-parameters. This was the least bad solution. .. _arc.ownership.restrictions.records: Ownership-qualified fields of structs and unions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A program is ill-formed if it declares a member of a C struct or union to have a nontrivially ownership-qualified type. .. admonition:: Rationale The resulting type would be non-POD in the C++ sense, but C does not give us very good language tools for managing the lifetime of aggregates, so it is more convenient to simply forbid them. It is still possible to manage this with a ``void*`` or an ``__unsafe_unretained`` object. This restriction does not apply in Objective-C++. However, nontrivally ownership-qualified types are considered non-POD: in C++11 terms, they are not trivially default constructible, copy constructible, move constructible, copy assignable, move assignable, or destructible. It is a violation of C++'s One Definition Rule to use a class outside of ARC that, under ARC, would have a nontrivially ownership-qualified member. .. admonition:: Rationale Unlike in C, we can express all the necessary ARC semantics for ownership-qualified subobjects as suboperations of the (default) special member functions for the class. These functions then become non-trivial. This has the non-obvious result that the class will have a non-trivial copy constructor and non-trivial destructor; if this would not normally be true outside of ARC, objects of the type will be passed and returned in an ABI-incompatible manner. .. _arc.ownership.inference: Ownership inference ------------------- .. _arc.ownership.inference.variables: Objects ^^^^^^^ If an object is declared with retainable object owner type, but without an explicit ownership qualifier, its type is implicitly adjusted to have ``__strong`` qualification. As a special case, if the object's base type is ``Class`` (possibly protocol-qualified), the type is adjusted to have ``__unsafe_unretained`` qualification instead. .. _arc.ownership.inference.indirect_parameters: Indirect parameters ^^^^^^^^^^^^^^^^^^^ If a function or method parameter has type ``T*``, where ``T`` is an ownership-unqualified retainable object pointer type, then: * if ``T`` is ``const``-qualified or ``Class``, then it is implicitly qualified with ``__unsafe_unretained``; * otherwise, it is implicitly qualified with ``__autoreleasing``. .. admonition:: Rationale ``__autoreleasing`` exists mostly for this case, the Cocoa convention for out-parameters. Since a pointer to ``const`` is obviously not an out-parameter, we instead use a type more useful for passing arrays. If the user instead intends to pass in a *mutable* array, inferring ``__autoreleasing`` is the wrong thing to do; this directs some of the caution in the following rules about writeback. Such a type written anywhere else would be ill-formed by the general rule requiring ownership qualifiers. This rule does not apply in Objective-C++ if a parameter's type is dependent in a template pattern and is only *instantiated* to a type which would be a pointer to an unqualified retainable object pointer type. Such code is still ill-formed. .. admonition:: Rationale The convention is very unlikely to be intentional in template code. .. _arc.ownership.inference.template.arguments: Template arguments ^^^^^^^^^^^^^^^^^^ If a template argument for a template type parameter is an retainable object owner type that does not have an explicit ownership qualifier, it is adjusted to have ``__strong`` qualification. This adjustment occurs regardless of whether the template argument was deduced or explicitly specified. .. admonition:: Rationale ``__strong`` is a useful default for containers (e.g., ``std::vector``), which would otherwise require explicit qualification. Moreover, unqualified retainable object pointer types are unlikely to be useful within templates, since they generally need to have a qualifier applied to the before being used. .. _arc.method-families: Method families =============== An Objective-C method may fall into a :arc-term:`method family`, which is a conventional set of behaviors ascribed to it by the Cocoa conventions. A method is in a certain method family if: * it has a ``objc_method_family`` attribute placing it in that family; or if not that, * it does not have an ``objc_method_family`` attribute placing it in a different or no family, and * its selector falls into the corresponding selector family, and * its signature obeys the added restrictions of the method family. A selector is in a certain selector family if, ignoring any leading underscores, the first component of the selector either consists entirely of the name of the method family or it begins with that name followed by a character other than a lowercase letter. For example, ``_perform:with:`` and ``performWith:`` would fall into the ``perform`` family (if we recognized one), but ``performing:with`` would not. The families and their added restrictions are: * ``alloc`` methods must return a retainable object pointer type. * ``copy`` methods must return a retainable object pointer type. * ``mutableCopy`` methods must return a retainable object pointer type. * ``new`` methods must return a retainable object pointer type. * ``init`` methods must be instance methods and must return an Objective-C pointer type. Additionally, a program is ill-formed if it declares or contains a call to an ``init`` method whose return type is neither ``id`` nor a pointer to a super-class or sub-class of the declaring class (if the method was declared on a class) or the static receiver type of the call (if it was declared on a protocol). .. admonition:: Rationale There are a fair number of existing methods with ``init``-like selectors which nonetheless don't follow the ``init`` conventions. Typically these are either accidental naming collisions or helper methods called during initialization. Because of the peculiar retain/release behavior of ``init`` methods, it's very important not to treat these methods as ``init`` methods if they aren't meant to be. It was felt that implicitly defining these methods out of the family based on the exact relationship between the return type and the declaring class would be much too subtle and fragile. Therefore we identify a small number of legitimate-seeming return types and call everything else an error. This serves the secondary purpose of encouraging programmers not to accidentally give methods names in the ``init`` family. Note that a method with an ``init``-family selector which returns a non-Objective-C type (e.g. ``void``) is perfectly well-formed; it simply isn't in the ``init`` family. A program is ill-formed if a method's declarations, implementations, and overrides do not all have the same method family. .. _arc.family.attribute: Explicit method family control ------------------------------ A method may be annotated with the ``objc_method_family`` attribute to precisely control which method family it belongs to. If a method in an ``@implementation`` does not have this attribute, but there is a method declared in the corresponding ``@interface`` that does, then the attribute is copied to the declaration in the ``@implementation``. The attribute is available outside of ARC, and may be tested for with the preprocessor query ``__has_attribute(objc_method_family)``. The attribute is spelled ``__attribute__((objc_method_family(`` *family* ``)))``. If *family* is ``none``, the method has no family, even if it would otherwise be considered to have one based on its selector and type. Otherwise, *family* must be one of ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``, in which case the method is considered to belong to the corresponding family regardless of its selector. It is an error if a method that is explicitly added to a family in this way does not meet the requirements of the family other than the selector naming convention. .. admonition:: Rationale The rules codified in this document describe the standard conventions of Objective-C. However, as these conventions have not heretofore been enforced by an unforgiving mechanical system, they are only imperfectly kept, especially as they haven't always even been precisely defined. While it is possible to define low-level ownership semantics with attributes like ``ns_returns_retained``, this attribute allows the user to communicate semantic intent, which is of use both to ARC (which, e.g., treats calls to ``init`` specially) and the static analyzer. .. _arc.family.semantics: Semantics of method families ---------------------------- A method's membership in a method family may imply non-standard semantics for its parameters and return type. Methods in the ``alloc``, ``copy``, ``mutableCopy``, and ``new`` families --- that is, methods in all the currently-defined families except ``init`` --- implicitly :ref:`return a retained object ` as if they were annotated with the ``ns_returns_retained`` attribute. This can be overridden by annotating the method with either of the ``ns_returns_autoreleased`` or ``ns_returns_not_retained`` attributes. Properties also follow same naming rules as methods. This means that those in the ``alloc``, ``copy``, ``mutableCopy``, and ``new`` families provide access to :ref:`retained objects `. This can be overridden by annotating the property with ``ns_returns_not_retained`` attribute. .. _arc.family.semantics.init: Semantics of ``init`` ^^^^^^^^^^^^^^^^^^^^^ Methods in the ``init`` family implicitly :ref:`consume ` their ``self`` parameter and :ref:`return a retained object `. Neither of these properties can be altered through attributes. A call to an ``init`` method with a receiver that is either ``self`` (possibly parenthesized or casted) or ``super`` is called a :arc-term:`delegate init call`. It is an error for a delegate init call to be made except from an ``init`` method, and excluding blocks within such methods. As an exception to the :ref:`usual rule `, the variable ``self`` is mutable in an ``init`` method and has the usual semantics for a ``__strong`` variable. However, it is undefined behavior and the program is ill-formed, no diagnostic required, if an ``init`` method attempts to use the previous value of ``self`` after the completion of a delegate init call. It is conventional, but not required, for an ``init`` method to return ``self``. It is undefined behavior for a program to cause two or more calls to ``init`` methods on the same object, except that each ``init`` method invocation may perform at most one delegate init call. .. _arc.family.semantics.result_type: Related result types ^^^^^^^^^^^^^^^^^^^^ Certain methods are candidates to have :arc-term:`related result types`: * class methods in the ``alloc`` and ``new`` method families * instance methods in the ``init`` family * the instance method ``self`` * outside of ARC, the instance methods ``retain`` and ``autorelease`` If the formal result type of such a method is ``id`` or protocol-qualified ``id``, or a type equal to the declaring class or a superclass, then it is said to have a related result type. In this case, when invoked in an explicit message send, it is assumed to return a type related to the type of the receiver: * if it is a class method, and the receiver is a class name ``T``, the message send expression has type ``T*``; otherwise * if it is an instance method, and the receiver has type ``T``, the message send expression has type ``T``; otherwise * the message send expression has the normal result type of the method. This is a new rule of the Objective-C language and applies outside of ARC. .. admonition:: Rationale ARC's automatic code emission is more prone than most code to signature errors, i.e. errors where a call was emitted against one method signature, but the implementing method has an incompatible signature. Having more precise type information helps drastically lower this risk, as well as catching a number of latent bugs. .. _arc.optimization: Optimization ============ Within this section, the word :arc-term:`function` will be used to refer to any structured unit of code, be it a C function, an Objective-C method, or a block. This specification describes ARC as performing specific ``retain`` and ``release`` operations on retainable object pointers at specific points during the execution of a program. These operations make up a non-contiguous subsequence of the computation history of the program. The portion of this sequence for a particular retainable object pointer for which a specific function execution is directly responsible is the :arc-term:`formal local retain history` of the object pointer. The corresponding actual sequence executed is the `dynamic local retain history`. However, under certain circumstances, ARC is permitted to re-order and eliminate operations in a manner which may alter the overall computation history beyond what is permitted by the general "as if" rule of C/C++ and the :ref:`restrictions ` on the implementation of ``retain`` and ``release``. .. admonition:: Rationale Specifically, ARC is sometimes permitted to optimize ``release`` operations in ways which might cause an object to be deallocated before it would otherwise be. Without this, it would be almost impossible to eliminate any ``retain``/``release`` pairs. For example, consider the following code: .. code-block:: objc id x = _ivar; [x foo]; If we were not permitted in any event to shorten the lifetime of the object in ``x``, then we would not be able to eliminate this retain and release unless we could prove that the message send could not modify ``_ivar`` (or deallocate ``self``). Since message sends are opaque to the optimizer, this is not possible, and so ARC's hands would be almost completely tied. ARC makes no guarantees about the execution of a computation history which contains undefined behavior. In particular, ARC makes no guarantees in the presence of race conditions. ARC may assume that any retainable object pointers it receives or generates are instantaneously valid from that point until a point which, by the concurrency model of the host language, happens-after the generation of the pointer and happens-before a release of that object (possibly via an aliasing pointer or indirectly due to destruction of a different object). .. admonition:: Rationale There is very little point in trying to guarantee correctness in the presence of race conditions. ARC does not have a stack-scanning garbage collector, and guaranteeing the atomicity of every load and store operation would be prohibitive and preclude a vast amount of optimization. ARC may assume that non-ARC code engages in sensible balancing behavior and does not rely on exact or minimum retain count values except as guaranteed by ``__strong`` object invariants or +1 transfer conventions. For example, if an object is provably double-retained and double-released, ARC may eliminate the inner retain and release; it does not need to guard against code which performs an unbalanced release followed by a "balancing" retain. .. _arc.optimization.liveness: Object liveness --------------- ARC may not allow a retainable object ``X`` to be deallocated at a time ``T`` in a computation history if: * ``X`` is the value stored in a ``__strong`` object ``S`` with :ref:`precise lifetime semantics `, or * ``X`` is the value stored in a ``__strong`` object ``S`` with imprecise lifetime semantics and, at some point after ``T`` but before the next store to ``S``, the computation history features a load from ``S`` and in some way depends on the value loaded, or * ``X`` is a value described as being released at the end of the current full-expression and, at some point after ``T`` but before the end of the full-expression, the computation history depends on that value. .. admonition:: Rationale The intent of the second rule is to say that objects held in normal ``__strong`` local variables may be released as soon as the value in the variable is no longer being used: either the variable stops being used completely or a new value is stored in the variable. The intent of the third rule is to say that return values may be released after they've been used. A computation history depends on a pointer value ``P`` if it: * performs a pointer comparison with ``P``, * loads from ``P``, * stores to ``P``, * depends on a pointer value ``Q`` derived via pointer arithmetic from ``P`` (including an instance-variable or field access), or * depends on a pointer value ``Q`` loaded from ``P``. Dependency applies only to values derived directly or indirectly from a particular expression result and does not occur merely because a separate pointer value dynamically aliases ``P``. Furthermore, this dependency is not carried by values that are stored to objects. .. admonition:: Rationale The restrictions on dependency are intended to make this analysis feasible by an optimizer with only incomplete information about a program. Essentially, dependence is carried to "obvious" uses of a pointer. Merely passing a pointer argument to a function does not itself cause dependence, but since generally the optimizer will not be able to prove that the function doesn't depend on that parameter, it will be forced to conservatively assume it does. Dependency propagates to values loaded from a pointer because those values might be invalidated by deallocating the object. For example, given the code ``__strong id x = p->ivar;``, ARC must not move the release of ``p`` to between the load of ``p->ivar`` and the retain of that value for storing into ``x``. Dependency does not propagate through stores of dependent pointer values because doing so would allow dependency to outlive the full-expression which produced the original value. For example, the address of an instance variable could be written to some global location and then freely accessed during the lifetime of the local, or a function could return an inner pointer of an object and store it to a local. These cases would be potentially impossible to reason about and so would basically prevent any optimizations based on imprecise lifetime. There are also uncommon enough to make it reasonable to require the precise-lifetime annotation if someone really wants to rely on them. Dependency does propagate through return values of pointer type. The compelling source of need for this rule is a property accessor which returns an un-autoreleased result; the calling function must have the chance to operate on the value, e.g. to retain it, before ARC releases the original pointer. Note again, however, that dependence does not survive a store, so ARC does not guarantee the continued validity of the return value past the end of the full-expression. .. _arc.optimization.object_lifetime: No object lifetime extension ---------------------------- If, in the formal computation history of the program, an object ``X`` has been deallocated by the time of an observable side-effect, then ARC must cause ``X`` to be deallocated by no later than the occurrence of that side-effect, except as influenced by the re-ordering of the destruction of objects. .. admonition:: Rationale This rule is intended to prohibit ARC from observably extending the lifetime of a retainable object, other than as specified in this document. Together with the rule limiting the transformation of releases, this rule requires ARC to eliminate retains and release only in pairs. ARC's power to reorder the destruction of objects is critical to its ability to do any optimization, for essentially the same reason that it must retain the power to decrease the lifetime of an object. Unfortunately, while it's generally poor style for the destruction of objects to have arbitrary side-effects, it's certainly possible. Hence the caveat. .. _arc.optimization.precise: Precise lifetime semantics -------------------------- In general, ARC maintains an invariant that a retainable object pointer held in a ``__strong`` object will be retained for the full formal lifetime of the object. Objects subject to this invariant have :arc-term:`precise lifetime semantics`. By default, local variables of automatic storage duration do not have precise lifetime semantics. Such objects are simply strong references which hold values of retainable object pointer type, and these values are still fully subject to the optimizations on values under local control. .. admonition:: Rationale Applying these precise-lifetime semantics strictly would be prohibitive. Many useful optimizations that might theoretically decrease the lifetime of an object would be rendered impossible. Essentially, it promises too much. A local variable of retainable object owner type and automatic storage duration may be annotated with the ``objc_precise_lifetime`` attribute to indicate that it should be considered to be an object with precise lifetime semantics. .. admonition:: Rationale Nonetheless, it is sometimes useful to be able to force an object to be released at a precise time, even if that object does not appear to be used. This is likely to be uncommon enough that the syntactic weight of explicitly requesting these semantics will not be burdensome, and may even make the code clearer. .. _arc.misc: Miscellaneous ============= .. _arc.misc.special_methods: Special methods --------------- .. _arc.misc.special_methods.retain: Memory management methods ^^^^^^^^^^^^^^^^^^^^^^^^^ A program is ill-formed if it contains a method definition, message send, or ``@selector`` expression for any of the following selectors: * ``autorelease`` * ``release`` * ``retain`` * ``retainCount`` .. admonition:: Rationale ``retainCount`` is banned because ARC robs it of consistent semantics. The others were banned after weighing three options for how to deal with message sends: **Honoring** them would work out very poorly if a programmer naively or accidentally tried to incorporate code written for manual retain/release code into an ARC program. At best, such code would do twice as much work as necessary; quite frequently, however, ARC and the explicit code would both try to balance the same retain, leading to crashes. The cost is losing the ability to perform "unrooted" retains, i.e. retains not logically corresponding to a strong reference in the object graph. **Ignoring** them would badly violate user expectations about their code. While it *would* make it easier to develop code simultaneously for ARC and non-ARC, there is very little reason to do so except for certain library developers. ARC and non-ARC translation units share an execution model and can seamlessly interoperate. Within a translation unit, a developer who faithfully maintains their code in non-ARC mode is suffering all the restrictions of ARC for zero benefit, while a developer who isn't testing the non-ARC mode is likely to be unpleasantly surprised if they try to go back to it. **Banning** them has the disadvantage of making it very awkward to migrate existing code to ARC. The best answer to that, given a number of other changes and restrictions in ARC, is to provide a specialized tool to assist users in that migration. Implementing these methods was banned because they are too integral to the semantics of ARC; many tricks which worked tolerably under manual reference counting will misbehave if ARC performs an ephemeral extra retain or two. If absolutely required, it is still possible to implement them in non-ARC code, for example in a category; the implementations must obey the :ref:`semantics ` laid out elsewhere in this document. .. _arc.misc.special_methods.dealloc: ``dealloc`` ^^^^^^^^^^^ A program is ill-formed if it contains a message send or ``@selector`` expression for the selector ``dealloc``. .. admonition:: Rationale There are no legitimate reasons to call ``dealloc`` directly. A class may provide a method definition for an instance method named ``dealloc``. This method will be called after the final ``release`` of the object but before it is deallocated or any of its instance variables are destroyed. The superclass's implementation of ``dealloc`` will be called automatically when the method returns. .. admonition:: Rationale Even though ARC destroys instance variables automatically, there are still legitimate reasons to write a ``dealloc`` method, such as freeing non-retainable resources. Failing to call ``[super dealloc]`` in such a method is nearly always a bug. Sometimes, the object is simply trying to prevent itself from being destroyed, but ``dealloc`` is really far too late for the object to be raising such objections. Somewhat more legitimately, an object may have been pool-allocated and should not be deallocated with ``free``; for now, this can only be supported with a ``dealloc`` implementation outside of ARC. Such an implementation must be very careful to do all the other work that ``NSObject``'s ``dealloc`` would, which is outside the scope of this document to describe. The instance variables for an ARC-compiled class will be destroyed at some point after control enters the ``dealloc`` method for the root class of the class. The ordering of the destruction of instance variables is unspecified, both within a single class and between subclasses and superclasses. .. admonition:: Rationale The traditional, non-ARC pattern for destroying instance variables is to destroy them immediately before calling ``[super dealloc]``. Unfortunately, message sends from the superclass are quite capable of reaching methods in the subclass, and those methods may well read or write to those instance variables. Making such message sends from dealloc is generally discouraged, since the subclass may well rely on other invariants that were broken during ``dealloc``, but it's not so inescapably dangerous that we felt comfortable calling it undefined behavior. Therefore we chose to delay destroying the instance variables to a point at which message sends are clearly disallowed: the point at which the root class's deallocation routines take over. In most code, the difference is not observable. It can, however, be observed if an instance variable holds a strong reference to an object whose deallocation will trigger a side-effect which must be carefully ordered with respect to the destruction of the super class. Such code violates the design principle that semantically important behavior should be explicit. A simple fix is to clear the instance variable manually during ``dealloc``; a more holistic solution is to move semantically important side-effects out of ``dealloc`` and into a separate teardown phase which can rely on working with well-formed objects. .. _arc.misc.autoreleasepool: ``@autoreleasepool`` -------------------- To simplify the use of autorelease pools, and to bring them under the control of the compiler, a new kind of statement is available in Objective-C. It is written ``@autoreleasepool`` followed by a *compound-statement*, i.e. by a new scope delimited by curly braces. Upon entry to this block, the current state of the autorelease pool is captured. When the block is exited normally, whether by fallthrough or directed control flow (such as ``return`` or ``break``), the autorelease pool is restored to the saved state, releasing all the objects in it. When the block is exited with an exception, the pool is not drained. ``@autoreleasepool`` may be used in non-ARC translation units, with equivalent semantics. A program is ill-formed if it refers to the ``NSAutoreleasePool`` class. .. admonition:: Rationale Autorelease pools are clearly important for the compiler to reason about, but it is far too much to expect the compiler to accurately reason about control dependencies between two calls. It is also very easy to accidentally forget to drain an autorelease pool when using the manual API, and this can significantly inflate the process's high-water-mark. The introduction of a new scope is unfortunate but basically required for sane interaction with the rest of the language. Not draining the pool during an unwind is apparently required by the Objective-C exceptions implementation. .. _arc.misc.self: ``self`` -------- The ``self`` parameter variable of an Objective-C method is never actually retained by the implementation. It is undefined behavior, or at least dangerous, to cause an object to be deallocated during a message send to that object. To make this safe, for Objective-C instance methods ``self`` is implicitly ``const`` unless the method is in the :ref:`init family `. Further, ``self`` is **always** implicitly ``const`` within a class method. .. admonition:: Rationale The cost of retaining ``self`` in all methods was found to be prohibitive, as it tends to be live across calls, preventing the optimizer from proving that the retain and release are unnecessary --- for good reason, as it's quite possible in theory to cause an object to be deallocated during its execution without this retain and release. Since it's extremely uncommon to actually do so, even unintentionally, and since there's no natural way for the programmer to remove this retain/release pair otherwise (as there is for other parameters by, say, making the variable ``__unsafe_unretained``), we chose to make this optimizing assumption and shift some amount of risk to the user. .. _arc.misc.enumeration: Fast enumeration iteration variables ------------------------------------ If a variable is declared in the condition of an Objective-C fast enumeration loop, and the variable has no explicit ownership qualifier, then it is qualified with ``const __strong`` and objects encountered during the enumeration are not actually retained. .. admonition:: Rationale This is an optimization made possible because fast enumeration loops promise to keep the objects retained during enumeration, and the collection itself cannot be synchronously modified. It can be overridden by explicitly qualifying the variable with ``__strong``, which will make the variable mutable again and cause the loop to retain the objects it encounters. .. _arc.misc.blocks: Blocks ------ The implicit ``const`` capture variables created when evaluating a block literal expression have the same ownership semantics as the local variables they capture. The capture is performed by reading from the captured variable and initializing the capture variable with that value; the capture variable is destroyed when the block literal is, i.e. at the end of the enclosing scope. The :ref:`inference ` rules apply equally to ``__block`` variables, which is a shift in semantics from non-ARC, where ``__block`` variables did not implicitly retain during capture. ``__block`` variables of retainable object owner type are moved off the stack by initializing the heap copy with the result of moving from the stack copy. With the exception of retains done as part of initializing a ``__strong`` parameter variable or reading a ``__weak`` variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a ``Block_copy``. The optimizer may remove such copies when it sees that the result is used only as an argument to a call. .. _arc.misc.exceptions: Exceptions ---------- By default in Objective C, ARC is not exception-safe for normal releases: * It does not end the lifetime of ``__strong`` variables when their scopes are abnormally terminated by an exception. * It does not perform releases which would occur at the end of a full-expression if that full-expression throws an exception. A program may be compiled with the option ``-fobjc-arc-exceptions`` in order to enable these, or with the option ``-fno-objc-arc-exceptions`` to explicitly disable them, with the last such argument "winning". .. admonition:: Rationale The standard Cocoa convention is that exceptions signal programmer error and are not intended to be recovered from. Making code exceptions-safe by default would impose severe runtime and code size penalties on code that typically does not actually care about exceptions safety. Therefore, ARC-generated code leaks by default on exceptions, which is just fine if the process is going to be immediately terminated anyway. Programs which do care about recovering from exceptions should enable the option. In Objective-C++, ``-fobjc-arc-exceptions`` is enabled by default. .. admonition:: Rationale C++ already introduces pervasive exceptions-cleanup code of the sort that ARC introduces. C++ programmers who have not already disabled exceptions are much more likely to actual require exception-safety. ARC does end the lifetimes of ``__weak`` objects when an exception terminates their scope unless exceptions are disabled in the compiler. .. admonition:: Rationale The consequence of a local ``__weak`` object not being destroyed is very likely to be corruption of the Objective-C runtime, so we want to be safer here. Of course, potentially massive leaks are about as likely to take down the process as this corruption is if the program does try to recover from exceptions. .. _arc.misc.interior: Interior pointers ----------------- An Objective-C method returning a non-retainable pointer may be annotated with the ``objc_returns_inner_pointer`` attribute to indicate that it returns a handle to the internal data of an object, and that this reference will be invalidated if the object is destroyed. When such a message is sent to an object, the object's lifetime will be extended until at least the earliest of: * the last use of the returned pointer, or any pointer derived from it, in the calling function or * the autorelease pool is restored to a previous state. .. admonition:: Rationale Rationale: not all memory and resources are managed with reference counts; it is common for objects to manage private resources in their own, private way. Typically these resources are completely encapsulated within the object, but some classes offer their users direct access for efficiency. If ARC is not aware of methods that return such "interior" pointers, its optimizations can cause the owning object to be reclaimed too soon. This attribute informs ARC that it must tread lightly. The extension rules are somewhat intentionally vague. The autorelease pool limit is there to permit a simple implementation to simply retain and autorelease the receiver. The other limit permits some amount of optimization. The phrase "derived from" is intended to encompass the results both of pointer transformations, such as casts and arithmetic, and of loading from such derived pointers; furthermore, it applies whether or not such derivations are applied directly in the calling code or by other utility code (for example, the C library routine ``strchr``). However, the implementation never need account for uses after a return from the code which calls the method returning an interior pointer. As an exception, no extension is required if the receiver is loaded directly from a ``__strong`` object with :ref:`precise lifetime semantics `. .. admonition:: Rationale Implicit autoreleases carry the risk of significantly inflating memory use, so it's important to provide users a way of avoiding these autoreleases. Tying this to precise lifetime semantics is ideal, as for local variables this requires a very explicit annotation, which allows ARC to trust the user with good cheer. .. _arc.misc.c-retainable: C retainable pointer types -------------------------- A type is a :arc-term:`C retainable pointer type` if it is a pointer to (possibly qualified) ``void`` or a pointer to a (possibly qualifier) ``struct`` or ``class`` type. .. admonition:: Rationale ARC does not manage pointers of CoreFoundation type (or any of the related families of retainable C pointers which interoperate with Objective-C for retain/release operation). In fact, ARC does not even know how to distinguish these types from arbitrary C pointer types. The intent of this concept is to filter out some obviously non-object types while leaving a hook for later tightening if a means of exhaustively marking CF types is made available. .. _arc.misc.c-retainable.audit: Auditing of C retainable pointer interfaces ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :when-revised:`[beginning Apple 4.0, LLVM 3.1]` A C function may be marked with the ``cf_audited_transfer`` attribute to express that, except as otherwise marked with attributes, it obeys the parameter (consuming vs. non-consuming) and return (retained vs. non-retained) conventions for a C function of its name, namely: * A parameter of C retainable pointer type is assumed to not be consumed unless it is marked with the ``cf_consumed`` attribute, and * A result of C retainable pointer type is assumed to not be returned retained unless the function is either marked ``cf_returns_retained`` or it follows the create/copy naming convention and is not marked ``cf_returns_not_retained``. A function obeys the :arc-term:`create/copy` naming convention if its name contains as a substring: * either "Create" or "Copy" not followed by a lowercase letter, or * either "create" or "copy" not followed by a lowercase letter and not preceded by any letter, whether uppercase or lowercase. A second attribute, ``cf_unknown_transfer``, signifies that a function's transfer semantics cannot be accurately captured using any of these annotations. A program is ill-formed if it annotates the same function with both ``cf_audited_transfer`` and ``cf_unknown_transfer``. A pragma is provided to facilitate the mass annotation of interfaces: .. code-block:: objc #pragma clang arc_cf_code_audited begin ... #pragma clang arc_cf_code_audited end All C functions declared within the extent of this pragma are treated as if annotated with the ``cf_audited_transfer`` attribute unless they otherwise have the ``cf_unknown_transfer`` attribute. The pragma is accepted in all language modes. A program is ill-formed if it attempts to change files, whether by including a file or ending the current file, within the extent of this pragma. It is possible to test for all the features in this section with ``__has_feature(arc_cf_code_audited)``. .. admonition:: Rationale A significant inconvenience in ARC programming is the necessity of interacting with APIs based around C retainable pointers. These features are designed to make it relatively easy for API authors to quickly review and annotate their interfaces, in turn improving the fidelity of tools such as the static analyzer and ARC. The single-file restriction on the pragma is designed to eliminate the risk of accidentally annotating some other header's interfaces. .. _arc.runtime: Runtime support =============== This section describes the interaction between the ARC runtime and the code generated by the ARC compiler. This is not part of the ARC language specification; instead, it is effectively a language-specific ABI supplement, akin to the "Itanium" generic ABI for C++. Ownership qualification does not alter the storage requirements for objects, except that it is undefined behavior if a ``__weak`` object is inadequately aligned for an object of type ``id``. The other qualifiers may be used on explicitly under-aligned memory. The runtime tracks ``__weak`` objects which holds non-null values. It is undefined behavior to direct modify a ``__weak`` object which is being tracked by the runtime except through an :ref:`objc_storeWeak `, :ref:`objc_destroyWeak `, or :ref:`objc_moveWeak ` call. The runtime must provide a number of new entrypoints which the compiler may emit, which are described in the remainder of this section. .. admonition:: Rationale Several of these functions are semantically equivalent to a message send; we emit calls to C functions instead because: * the machine code to do so is significantly smaller, * it is much easier to recognize the C functions in the ARC optimizer, and * a sufficient sophisticated runtime may be able to avoid the message send in common cases. Several other of these functions are "fused" operations which can be described entirely in terms of other operations. We use the fused operations primarily as a code-size optimization, although in some cases there is also a real potential for avoiding redundant operations in the runtime. .. _arc.runtime.objc_autorelease: ``id objc_autorelease(id value);`` ---------------------------------- *Precondition:* ``value`` is null or a pointer to a valid object. If ``value`` is null, this call has no effect. Otherwise, it adds the object to the innermost autorelease pool exactly as if the object had been sent the ``autorelease`` message. Always returns ``value``. .. _arc.runtime.objc_autoreleasePoolPop: ``void objc_autoreleasePoolPop(void *pool);`` --------------------------------------------- *Precondition:* ``pool`` is the result of a previous call to :ref:`objc_autoreleasePoolPush ` on the current thread, where neither ``pool`` nor any enclosing pool have previously been popped. Releases all the objects added to the given autorelease pool and any autorelease pools it encloses, then sets the current autorelease pool to the pool directly enclosing ``pool``. .. _arc.runtime.objc_autoreleasePoolPush: ``void *objc_autoreleasePoolPush(void);`` ----------------------------------------- Creates a new autorelease pool that is enclosed by the current pool, makes that the current pool, and returns an opaque "handle" to it. .. admonition:: Rationale While the interface is described as an explicit hierarchy of pools, the rules allow the implementation to just keep a stack of objects, using the stack depth as the opaque pool handle. .. _arc.runtime.objc_autoreleaseReturnValue: ``id objc_autoreleaseReturnValue(id value);`` --------------------------------------------- *Precondition:* ``value`` is null or a pointer to a valid object. If ``value`` is null, this call has no effect. Otherwise, it makes a best effort to hand off ownership of a retain count on the object to a call to :ref:`objc_retainAutoreleasedReturnValue ` for the same object in an enclosing call frame. If this is not possible, the object is autoreleased as above. Always returns ``value``. .. _arc.runtime.objc_copyWeak: ``void objc_copyWeak(id *dest, id *src);`` ------------------------------------------ *Precondition:* ``src`` is a valid pointer which either contains a null pointer or has been registered as a ``__weak`` object. ``dest`` is a valid pointer which has not been registered as a ``__weak`` object. ``dest`` is initialized to be equivalent to ``src``, potentially registering it with the runtime. Equivalent to the following code: .. code-block:: objc void objc_copyWeak(id *dest, id *src) { objc_release(objc_initWeak(dest, objc_loadWeakRetained(src))); } Must be atomic with respect to calls to ``objc_storeWeak`` on ``src``. .. _arc.runtime.objc_destroyWeak: ``void objc_destroyWeak(id *object);`` -------------------------------------- *Precondition:* ``object`` is a valid pointer which either contains a null pointer or has been registered as a ``__weak`` object. ``object`` is unregistered as a weak object, if it ever was. The current value of ``object`` is left unspecified; otherwise, equivalent to the following code: .. code-block:: objc void objc_destroyWeak(id *object) { objc_storeWeak(object, nil); } Does not need to be atomic with respect to calls to ``objc_storeWeak`` on ``object``. .. _arc.runtime.objc_initWeak: ``id objc_initWeak(id *object, id value);`` ------------------------------------------- *Precondition:* ``object`` is a valid pointer which has not been registered as a ``__weak`` object. ``value`` is null or a pointer to a valid object. If ``value`` is a null pointer or the object to which it points has begun deallocation, ``object`` is zero-initialized. Otherwise, ``object`` is registered as a ``__weak`` object pointing to ``value``. Equivalent to the following code: .. code-block:: objc id objc_initWeak(id *object, id value) { *object = nil; return objc_storeWeak(object, value); } Returns the value of ``object`` after the call. Does not need to be atomic with respect to calls to ``objc_storeWeak`` on ``object``. .. _arc.runtime.objc_loadWeak: ``id objc_loadWeak(id *object);`` --------------------------------- *Precondition:* ``object`` is a valid pointer which either contains a null pointer or has been registered as a ``__weak`` object. If ``object`` is registered as a ``__weak`` object, and the last value stored into ``object`` has not yet been deallocated or begun deallocation, retains and autoreleases that value and returns it. Otherwise returns null. Equivalent to the following code: .. code-block:: objc id objc_loadWeak(id *object) { return objc_autorelease(objc_loadWeakRetained(object)); } Must be atomic with respect to calls to ``objc_storeWeak`` on ``object``. .. admonition:: Rationale Loading weak references would be inherently prone to race conditions without the retain. .. _arc.runtime.objc_loadWeakRetained: ``id objc_loadWeakRetained(id *object);`` ----------------------------------------- *Precondition:* ``object`` is a valid pointer which either contains a null pointer or has been registered as a ``__weak`` object. If ``object`` is registered as a ``__weak`` object, and the last value stored into ``object`` has not yet been deallocated or begun deallocation, retains that value and returns it. Otherwise returns null. Must be atomic with respect to calls to ``objc_storeWeak`` on ``object``. .. _arc.runtime.objc_moveWeak: ``void objc_moveWeak(id *dest, id *src);`` ------------------------------------------ *Precondition:* ``src`` is a valid pointer which either contains a null pointer or has been registered as a ``__weak`` object. ``dest`` is a valid pointer which has not been registered as a ``__weak`` object. ``dest`` is initialized to be equivalent to ``src``, potentially registering it with the runtime. ``src`` may then be left in its original state, in which case this call is equivalent to :ref:`objc_copyWeak `, or it may be left as null. Must be atomic with respect to calls to ``objc_storeWeak`` on ``src``. .. _arc.runtime.objc_release: ``void objc_release(id value);`` -------------------------------- *Precondition:* ``value`` is null or a pointer to a valid object. If ``value`` is null, this call has no effect. Otherwise, it performs a release operation exactly as if the object had been sent the ``release`` message. .. _arc.runtime.objc_retain: ``id objc_retain(id value);`` ----------------------------- *Precondition:* ``value`` is null or a pointer to a valid object. If ``value`` is null, this call has no effect. Otherwise, it performs a retain operation exactly as if the object had been sent the ``retain`` message. Always returns ``value``. .. _arc.runtime.objc_retainAutorelease: ``id objc_retainAutorelease(id value);`` ---------------------------------------- *Precondition:* ``value`` is null or a pointer to a valid object. If ``value`` is null, this call has no effect. Otherwise, it performs a retain operation followed by an autorelease operation. Equivalent to the following code: .. code-block:: objc id objc_retainAutorelease(id value) { return objc_autorelease(objc_retain(value)); } Always returns ``value``. .. _arc.runtime.objc_retainAutoreleaseReturnValue: ``id objc_retainAutoreleaseReturnValue(id value);`` --------------------------------------------------- *Precondition:* ``value`` is null or a pointer to a valid object. If ``value`` is null, this call has no effect. Otherwise, it performs a retain operation followed by the operation described in :ref:`objc_autoreleaseReturnValue `. Equivalent to the following code: .. code-block:: objc id objc_retainAutoreleaseReturnValue(id value) { return objc_autoreleaseReturnValue(objc_retain(value)); } Always returns ``value``. .. _arc.runtime.objc_retainAutoreleasedReturnValue: ``id objc_retainAutoreleasedReturnValue(id value);`` ---------------------------------------------------- *Precondition:* ``value`` is null or a pointer to a valid object. If ``value`` is null, this call has no effect. Otherwise, it attempts to accept a hand off of a retain count from a call to :ref:`objc_autoreleaseReturnValue ` on ``value`` in a recently-called function or something it calls. If that fails, it performs a retain operation exactly like :ref:`objc_retain `. Always returns ``value``. .. _arc.runtime.objc_retainBlock: ``id objc_retainBlock(id value);`` ---------------------------------- *Precondition:* ``value`` is null or a pointer to a valid block object. If ``value`` is null, this call has no effect. Otherwise, if the block pointed to by ``value`` is still on the stack, it is copied to the heap and the address of the copy is returned. Otherwise a retain operation is performed on the block exactly as if it had been sent the ``retain`` message. .. _arc.runtime.objc_storeStrong: ``id objc_storeStrong(id *object, id value);`` ---------------------------------------------- *Precondition:* ``object`` is a valid pointer to a ``__strong`` object which is adequately aligned for a pointer. ``value`` is null or a pointer to a valid object. Performs the complete sequence for assigning to a ``__strong`` object of non-block type [*]_. Equivalent to the following code: .. code-block:: objc - id objc_storeStrong(id *object, id value) { - value = [value retain]; + void objc_storeStrong(id *object, id value) { id oldValue = *object; + value = [value retain]; *object = value; [oldValue release]; - return value; } - -Always returns ``value``. .. [*] This does not imply that a ``__strong`` object of block type is an invalid argument to this function. Rather it implies that an ``objc_retain`` and not an ``objc_retainBlock`` operation will be emitted if the argument is a block. .. _arc.runtime.objc_storeWeak: ``id objc_storeWeak(id *object, id value);`` -------------------------------------------- *Precondition:* ``object`` is a valid pointer which either contains a null pointer or has been registered as a ``__weak`` object. ``value`` is null or a pointer to a valid object. If ``value`` is a null pointer or the object to which it points has begun deallocation, ``object`` is assigned null and unregistered as a ``__weak`` object. Otherwise, ``object`` is registered as a ``__weak`` object or has its registration updated to point to ``value``. Returns the value of ``object`` after the call. Index: vendor/clang/dist/docs/ReleaseNotes.rst =================================================================== --- vendor/clang/dist/docs/ReleaseNotes.rst (revision 313882) +++ vendor/clang/dist/docs/ReleaseNotes.rst (revision 313883) @@ -1,209 +1,278 @@ ======================================= Clang 4.0.0 (In-Progress) Release Notes ======================================= .. contents:: :local: :depth: 2 Written by the `LLVM Team `_ .. warning:: These are in-progress notes for the upcoming Clang 4.0.0 release. You may prefer the `Clang 3.9 Release Notes `_. Introduction ============ -This document contains the release notes for the Clang C/C++/Objective-C +This document contains the release notes for the Clang C/C++/Objective-C/OpenCL frontend, part of the LLVM Compiler Infrastructure, release 4.0.0. Here we describe the status of Clang in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see `the LLVM documentation `_. All LLVM releases may be downloaded from the `LLVM releases web site `_. For more information about Clang or LLVM, including information about the latest release, please check out the main please see the `Clang Web Site `_ or the `LLVM Web Site `_. What's New in Clang 4.0.0? ========================== Some of the major new features and improvements to Clang are listed here. Generic improvements to Clang as a whole or to its underlying infrastructure are described first, followed by language-specific sections with improvements to Clang's support for those languages. Major New Features ------------------ - The ``diagnose_if`` attribute has been added to clang. This attribute allows clang to emit a warning or error if a function call meets one or more user-specified conditions. - Enhanced devirtualization with `-fstrict-vtable-pointers `_. Clang devirtualizes across different basic blocks, like loops: .. code-block:: c++ struct A { virtual void foo(); }; void indirect(A &a, int n) { for (int i = 0 ; i < n; i++) a.foo(); } void test(int n) { A a; indirect(a, n); } - ... Improvements to ThinLTO (-flto=thin) ------------------------------------ - Integration with profile data (PGO). When available, profile data enables more accurate function importing decisions, as well as cross-module indirect call promotion. - Significant build-time and binary-size improvements when compiling with debug info (-g). Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ... New Compiler Flags ------------------ The option -Og has been added to optimize the debugging experience. For now, this option is exactly the same as -O1. However, in the future, some other optimizations might be enabled or disabled. The option -MJ has been added to simplify adding JSON compilation database output into existing build systems. The option .... New Pragmas in Clang ----------------------- Clang now supports the ... Attribute Changes in Clang -------------------------- - ... Windows Support --------------- Clang's support for building native Windows programs ... C Language Changes in Clang --------------------------- - ... ... C11 Feature Support ^^^^^^^^^^^^^^^^^^^ ... C++ Language Changes in Clang ----------------------------- ... C++1z Feature Support ^^^^^^^^^^^^^^^^^^^^^ ... Objective-C Language Changes in Clang ------------------------------------- ... OpenCL C Language Changes in Clang ---------------------------------- -... +**The following bugs in the OpenCL header have been fixed:** + +* Added missing ``overloadable`` and ``convergent`` attributes. +* Removed some erroneous extra ``native_*`` functions. + +**The following bugs in the generation of metadata have been fixed:** + +* Corrected the SPIR version depending on the OpenCL version. +* Source level address spaces are taken from the SPIR specification. +* Image types now contain no access qualifier. + +**The following bugs in the AMD target have been fixed:** + +* Corrected the bitwidth of ``size_t`` and NULL pointer value with respect to + address spaces. +* Added ``cl_khr_subgroups``, ``cl_amd_media_ops`` and ``cl_amd_media_ops2`` + extensions. +* Added ``cl-denorms-are-zero`` support. +* Changed address spaces for image objects to be ``constant``. +* Added little-endian. + +**The following bugs in OpenCL 2.0 have been fixed:** + +* Fixed pipe builtin function return type, added extra argument to generated + IR intrinsics to propagate size and alignment information of the pipe packed + type. +* Improved pipe type to accommodate access qualifiers. +* Added correct address space to the ObjC block generation and ``enqueue_kernel`` + prototype. +* Improved handling of integer parameters of ``enqueue_kernel`` prototype. We + now allow ``size_t`` instead of ``int`` for specifying block parameter sizes. +* Allow using NULL (aka ``CLK_NULL_QUEUE``) with ``queue_t``. + + +**Improved the following diagnostics:** + +* Disallow address spaces other than ``global`` for kernel pointer parameters. +* Correct the use of half type argument and pointer assignment with + dereferencing. +* Disallow variadic arguments in functions and blocks. +* Allow partial initializer for array and struct. + +**Some changes to OpenCL extensions have been made:** + +* Added ``cl_khr_mipmap_image``. +* Added ``-cl-ext`` flag to allow overwriting supported extensions otherwise + set by the target compiled for (Example: ``-cl-ext=-all,+cl_khr_fp16``). +* New types and functions can now be flexibly added to extensions using the + following pragmas instead of modifying the Clang source code: + + .. code-block:: c + + #pragma OPENCL EXTENSION the_new_extension_name : begin + // declare types and functions associated with the extension here + #pragma OPENCL EXTENSION the_new_extension_name : end + + +**Miscellaneous changes:** + +* Fix ``__builtin_astype`` to cast between different address space objects. +* Allow using ``opencl_unroll_hint`` with earlier OpenCL versions than 2.0. +* Improved handling of floating point literal to default to single precision if + fp64 extension is not enabled. +* Refactor ``sampler_t`` implementation to simplify initializer representation + which is now handled as a compiler builtin function with an integer value + passed into it. +* Change fake address space map to use the SPIR convention. +* Added `the OpenCL manual + `_ to Clang + documentation. OpenMP Support in Clang ---------------------------------- ... Internal API Changes -------------------- These are major API changes that have happened since the 3.9 release of Clang. If upgrading an external codebase that uses Clang as a library, this section should help get you past the largest hurdles of upgrading. - ... AST Matchers ------------ ... libclang -------- ... With the option --show-description, scan-build's list of defects will also show the description of the defects. Static Analyzer --------------- ... Core Analysis Improvements ========================== - ... New Issues Found ================ - ... Python Binding Changes ---------------------- The following methods have been added: - ... Significant Known Problems ========================== Additional Information ====================== A wide variety of additional information is available on the `Clang web page `_. The web page contains versions of the API documentation which are up-to-date with the Subversion version of the source code. You can access versions of these documents specific to this release by going into the "``clang/docs/``" directory in the Clang tree. If you have any questions or comments about Clang, please feel free to contact us via the `mailing list `_. Index: vendor/clang/dist/docs/UsersManual.rst =================================================================== --- vendor/clang/dist/docs/UsersManual.rst (revision 313882) +++ vendor/clang/dist/docs/UsersManual.rst (revision 313883) @@ -1,2690 +1,2727 @@ ============================ Clang Compiler User's Manual ============================ .. include:: .. contents:: :local: Introduction ============ The Clang Compiler is an open-source compiler for the C family of programming languages, aiming to be the best in class implementation of these languages. Clang builds on the LLVM optimizer and code generator, allowing it to provide high-quality optimization and code generation support for many targets. For more general information, please see the `Clang Web Site `_ or the `LLVM Web Site `_. This document describes important notes about using Clang as a compiler for an end-user, documenting the supported features, command line options, etc. If you are interested in using Clang to build a tool that processes code, please see :doc:`InternalsManual`. If you are interested in the `Clang Static Analyzer `_, please see its web page. Clang is one component in a complete toolchain for C family languages. A separate document describes the other pieces necessary to :doc:`assemble a complete toolchain `. Clang is designed to support the C family of programming languages, which includes :ref:`C `, :ref:`Objective-C `, :ref:`C++ `, and :ref:`Objective-C++ ` as well as many dialects of those. For language-specific information, please see the corresponding language specific section: - :ref:`C Language `: K&R C, ANSI C89, ISO C90, ISO C94 (C89+AMD1), ISO C99 (+TC1, TC2, TC3). - :ref:`Objective-C Language `: ObjC 1, ObjC 2, ObjC 2.1, plus variants depending on base language. - :ref:`C++ Language ` - :ref:`Objective C++ Language ` - :ref:`OpenCL C Language `: v1.0, v1.1, v1.2, v2.0. In addition to these base languages and their dialects, Clang supports a broad variety of language extensions, which are documented in the corresponding language section. These extensions are provided to be compatible with the GCC, Microsoft, and other popular compilers as well as to improve functionality through Clang-specific features. The Clang driver and language features are intentionally designed to be as compatible with the GNU GCC compiler as reasonably possible, easing migration from GCC to Clang. In most cases, code "just works". Clang also provides an alternative driver, :ref:`clang-cl`, that is designed to be compatible with the Visual C++ compiler, cl.exe. In addition to language specific features, Clang has a variety of features that depend on what CPU architecture or operating system is being compiled for. Please see the :ref:`Target-Specific Features and Limitations ` section for more details. The rest of the introduction introduces some basic :ref:`compiler terminology ` that is used throughout this manual and contains a basic :ref:`introduction to using Clang ` as a command line compiler. .. _terminology: Terminology ----------- Front end, parser, backend, preprocessor, undefined behavior, diagnostic, optimizer .. _basicusage: Basic Usage ----------- Intro to how to use a C compiler for newbies. compile + link compile then link debug info enabling optimizations picking a language to use, defaults to C11 by default. Autosenses based on extension. using a makefile Command Line Options ==================== This section is generally an index into other sections. It does not go into depth on the ones that are covered by other sections. However, the first part introduces the language selection and other high level options like :option:`-c`, :option:`-g`, etc. Options to Control Error and Warning Messages --------------------------------------------- .. option:: -Werror Turn warnings into errors. .. This is in plain monospaced font because it generates the same label as .. -Werror, and Sphinx complains. ``-Werror=foo`` Turn warning "foo" into an error. .. option:: -Wno-error=foo Turn warning "foo" into an warning even if :option:`-Werror` is specified. .. option:: -Wfoo Enable warning "foo". See the :doc:`diagnostics reference ` for a complete list of the warning flags that can be specified in this way. .. option:: -Wno-foo Disable warning "foo". .. option:: -w Disable all diagnostics. .. option:: -Weverything :ref:`Enable all diagnostics. ` .. option:: -pedantic Warn on language extensions. .. option:: -pedantic-errors Error on language extensions. .. option:: -Wsystem-headers Enable warnings from system headers. .. option:: -ferror-limit=123 Stop emitting diagnostics after 123 errors have been produced. The default is 20, and the error limit can be disabled with `-ferror-limit=0`. .. option:: -ftemplate-backtrace-limit=123 Only emit up to 123 template instantiation notes within the template instantiation backtrace for a single warning or error. The default is 10, and the limit can be disabled with `-ftemplate-backtrace-limit=0`. .. _cl_diag_formatting: Formatting of Diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^ Clang aims to produce beautiful diagnostics by default, particularly for new users that first come to Clang. However, different people have different preferences, and sometimes Clang is driven not by a human, but by a program that wants consistent and easily parsable output. For these cases, Clang provides a wide range of options to control the exact output format of the diagnostics that it generates. .. _opt_fshow-column: **-f[no-]show-column** Print column number in diagnostic. This option, which defaults to on, controls whether or not Clang prints the column number of a diagnostic. For example, when this is enabled, Clang will print something like: :: test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] #endif bad ^ // When this is disabled, Clang will print "test.c:28: warning..." with no column number. The printed column numbers count bytes from the beginning of the line; take care if your source contains multibyte characters. .. _opt_fshow-source-location: **-f[no-]show-source-location** Print source file/line/column information in diagnostic. This option, which defaults to on, controls whether or not Clang prints the filename, line number and column number of a diagnostic. For example, when this is enabled, Clang will print something like: :: test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] #endif bad ^ // When this is disabled, Clang will not print the "test.c:28:8: " part. .. _opt_fcaret-diagnostics: **-f[no-]caret-diagnostics** Print source line and ranges from source code in diagnostic. This option, which defaults to on, controls whether or not Clang prints the source line, source ranges, and caret when emitting a diagnostic. For example, when this is enabled, Clang will print something like: :: test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] #endif bad ^ // **-f[no-]color-diagnostics** This option, which defaults to on when a color-capable terminal is detected, controls whether or not Clang prints diagnostics in color. When this option is enabled, Clang will use colors to highlight specific parts of the diagnostic, e.g., .. nasty hack to not lose our dignity .. raw:: html
          test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens]
          #endif bad
                 ^
                 //
        
When this is disabled, Clang will just print: :: test.c:2:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] #endif bad ^ // **-fansi-escape-codes** Controls whether ANSI escape codes are used instead of the Windows Console API to output colored diagnostics. This option is only used on Windows and defaults to off. .. option:: -fdiagnostics-format=clang/msvc/vi Changes diagnostic output format to better match IDEs and command line tools. This option controls the output format of the filename, line number, and column printed in diagnostic messages. The options, and their affect on formatting a simple conversion diagnostic, follow: **clang** (default) :: t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' **msvc** :: t.c(3,11) : warning: conversion specifies type 'char *' but the argument has type 'int' **vi** :: t.c +3:11: warning: conversion specifies type 'char *' but the argument has type 'int' .. _opt_fdiagnostics-show-option: **-f[no-]diagnostics-show-option** Enable ``[-Woption]`` information in diagnostic line. This option, which defaults to on, controls whether or not Clang prints the associated :ref:`warning group ` option name when outputting a warning diagnostic. For example, in this output: :: test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] #endif bad ^ // Passing **-fno-diagnostics-show-option** will prevent Clang from printing the [:ref:`-Wextra-tokens `] information in the diagnostic. This information tells you the flag needed to enable or disable the diagnostic, either from the command line or through :ref:`#pragma GCC diagnostic `. .. _opt_fdiagnostics-show-category: .. option:: -fdiagnostics-show-category=none/id/name Enable printing category information in diagnostic line. This option, which defaults to "none", controls whether or not Clang prints the category associated with a diagnostic when emitting it. Each diagnostic may or many not have an associated category, if it has one, it is listed in the diagnostic categorization field of the diagnostic line (in the []'s). For example, a format string warning will produce these three renditions based on the setting of this option: :: t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat] t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat,1] t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat,Format String] This category can be used by clients that want to group diagnostics by category, so it should be a high level category. We want dozens of these, not hundreds or thousands of them. .. _opt_fdiagnostics-show-hotness: **-f[no-]diagnostics-show-hotness** Enable profile hotness information in diagnostic line. This option, which defaults to off, controls whether Clang prints the profile hotness associated with a diagnostics in the presence of profile-guided optimization information. This is currently supported with optimization remarks (see :ref:`Options to Emit Optimization Reports `). The hotness information allows users to focus on the hot optimization remarks that are likely to be more relevant for run-time performance. For example, in this output, the block containing the callsite of `foo` was executed 3000 times according to the profile data: :: s.c:7:10: remark: foo inlined into bar (hotness: 3000) [-Rpass-analysis=inline] sum += foo(x, x - 2); ^ .. _opt_fdiagnostics-fixit-info: **-f[no-]diagnostics-fixit-info** Enable "FixIt" information in the diagnostics output. This option, which defaults to on, controls whether or not Clang prints the information on how to fix a specific diagnostic underneath it when it knows. For example, in this output: :: test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] #endif bad ^ // Passing **-fno-diagnostics-fixit-info** will prevent Clang from printing the "//" line at the end of the message. This information is useful for users who may not understand what is wrong, but can be confusing for machine parsing. .. _opt_fdiagnostics-print-source-range-info: **-fdiagnostics-print-source-range-info** Print machine parsable information about source ranges. This option makes Clang print information about source ranges in a machine parsable format after the file/line/column number information. The information is a simple sequence of brace enclosed ranges, where each range lists the start and end line/column locations. For example, in this output: :: exprs.c:47:15:{47:8-47:14}{47:17-47:24}: error: invalid operands to binary expression ('int *' and '_Complex float') P = (P-42) + Gamma*4; ~~~~~~ ^ ~~~~~~~ The {}'s are generated by -fdiagnostics-print-source-range-info. The printed column numbers count bytes from the beginning of the line; take care if your source contains multibyte characters. .. option:: -fdiagnostics-parseable-fixits Print Fix-Its in a machine parseable form. This option makes Clang print available Fix-Its in a machine parseable format at the end of diagnostics. The following example illustrates the format: :: fix-it:"t.cpp":{7:25-7:29}:"Gamma" The range printed is a half-open range, so in this example the characters at column 25 up to but not including column 29 on line 7 in t.cpp should be replaced with the string "Gamma". Either the range or the replacement string may be empty (representing strict insertions and strict erasures, respectively). Both the file name and the insertion string escape backslash (as "\\\\"), tabs (as "\\t"), newlines (as "\\n"), double quotes(as "\\"") and non-printable characters (as octal "\\xxx"). The printed column numbers count bytes from the beginning of the line; take care if your source contains multibyte characters. .. option:: -fno-elide-type Turns off elision in template type printing. The default for template type printing is to elide as many template arguments as possible, removing those which are the same in both template types, leaving only the differences. Adding this flag will print all the template arguments. If supported by the terminal, highlighting will still appear on differing arguments. Default: :: t.cc:4:5: note: candidate function not viable: no known conversion from 'vector>>' to 'vector>>' for 1st argument; -fno-elide-type: :: t.cc:4:5: note: candidate function not viable: no known conversion from 'vector>>' to 'vector>>' for 1st argument; .. option:: -fdiagnostics-show-template-tree Template type diffing prints a text tree. For diffing large templated types, this option will cause Clang to display the templates as an indented text tree, one argument per line, with differences marked inline. This is compatible with -fno-elide-type. Default: :: t.cc:4:5: note: candidate function not viable: no known conversion from 'vector>>' to 'vector>>' for 1st argument; With :option:`-fdiagnostics-show-template-tree`: :: t.cc:4:5: note: candidate function not viable: no known conversion for 1st argument; vector< map< [...], map< [float != double], [...]>>> .. _cl_diag_warning_groups: Individual Warning Groups ^^^^^^^^^^^^^^^^^^^^^^^^^ TODO: Generate this from tblgen. Define one anchor per warning group. .. _opt_wextra-tokens: .. option:: -Wextra-tokens Warn about excess tokens at the end of a preprocessor directive. This option, which defaults to on, enables warnings about extra tokens at the end of preprocessor directives. For example: :: test.c:28:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] #endif bad ^ These extra tokens are not strictly conforming, and are usually best handled by commenting them out. .. option:: -Wambiguous-member-template Warn about unqualified uses of a member template whose name resolves to another template at the location of the use. This option, which defaults to on, enables a warning in the following code: :: template struct set{}; template struct trait { typedef const T& type; }; struct Value { template void set(typename trait::type value) {} }; void foo() { Value v; v.set(3.2); } C++ [basic.lookup.classref] requires this to be an error, but, because it's hard to work around, Clang downgrades it to a warning as an extension. .. option:: -Wbind-to-temporary-copy Warn about an unusable copy constructor when binding a reference to a temporary. This option enables warnings about binding a reference to a temporary when the temporary doesn't have a usable copy constructor. For example: :: struct NonCopyable { NonCopyable(); private: NonCopyable(const NonCopyable&); }; void foo(const NonCopyable&); void bar() { foo(NonCopyable()); // Disallowed in C++98; allowed in C++11. } :: struct NonCopyable2 { NonCopyable2(); NonCopyable2(NonCopyable2&); }; void foo(const NonCopyable2&); void bar() { foo(NonCopyable2()); // Disallowed in C++98; allowed in C++11. } Note that if ``NonCopyable2::NonCopyable2()`` has a default argument whose instantiation produces a compile error, that error will still be a hard error in C++98 mode even if this warning is turned off. Options to Control Clang Crash Diagnostics ------------------------------------------ As unbelievable as it may sound, Clang does crash from time to time. Generally, this only occurs to those living on the `bleeding edge `_. Clang goes to great lengths to assist you in filing a bug report. Specifically, Clang generates preprocessed source file(s) and associated run script(s) upon a crash. These files should be attached to a bug report to ease reproducibility of the failure. Below are the command line options to control the crash diagnostics. .. option:: -fno-crash-diagnostics Disable auto-generation of preprocessed source files during a clang crash. The -fno-crash-diagnostics flag can be helpful for speeding the process of generating a delta reduced test case. .. _rpass: Options to Emit Optimization Reports ------------------------------------ Optimization reports trace, at a high-level, all the major decisions done by compiler transformations. For instance, when the inliner decides to inline function ``foo()`` into ``bar()``, or the loop unroller decides to unroll a loop N times, or the vectorizer decides to vectorize a loop body. Clang offers a family of flags which the optimizers can use to emit a diagnostic in three cases: 1. When the pass makes a transformation (`-Rpass`). 2. When the pass fails to make a transformation (`-Rpass-missed`). 3. When the pass determines whether or not to make a transformation (`-Rpass-analysis`). NOTE: Although the discussion below focuses on `-Rpass`, the exact same options apply to `-Rpass-missed` and `-Rpass-analysis`. Since there are dozens of passes inside the compiler, each of these flags take a regular expression that identifies the name of the pass which should emit the associated diagnostic. For example, to get a report from the inliner, compile the code with: .. code-block:: console $ clang -O2 -Rpass=inline code.cc -o code code.cc:4:25: remark: foo inlined into bar [-Rpass=inline] int bar(int j) { return foo(j, j - 2); } ^ Note that remarks from the inliner are identified with `[-Rpass=inline]`. To request a report from every optimization pass, you should use `-Rpass=.*` (in fact, you can use any valid POSIX regular expression). However, do not expect a report from every transformation made by the compiler. Optimization remarks do not really make sense outside of the major transformations (e.g., inlining, vectorization, loop optimizations) and not every optimization pass supports this feature. Note that when using profile-guided optimization information, profile hotness information can be included in the remarks (see :ref:`-fdiagnostics-show-hotness `). Current limitations ^^^^^^^^^^^^^^^^^^^ 1. Optimization remarks that refer to function names will display the mangled name of the function. Since these remarks are emitted by the back end of the compiler, it does not know anything about the input language, nor its mangling rules. 2. Some source locations are not displayed correctly. The front end has a more detailed source location tracking than the locations included in the debug info (e.g., the front end can locate code inside macro expansions). However, the locations used by `-Rpass` are translated from debug annotations. That translation can be lossy, which results in some remarks having no location information. Other Options ------------- Clang options that that don't fit neatly into other categories. .. option:: -MV When emitting a dependency file, use formatting conventions appropriate for NMake or Jom. Ignored unless another option causes Clang to emit a dependency file. When Clang emits a dependency file (e.g., you supplied the -M option) most filenames can be written to the file without any special formatting. Different Make tools will treat different sets of characters as "special" and use different conventions for telling the Make tool that the character is actually part of the filename. Normally Clang uses backslash to "escape" a special character, which is the convention used by GNU Make. The -MV option tells Clang to put double-quotes around the entire filename, which is the convention used by NMake and Jom. Language and Target-Independent Features ======================================== Controlling Errors and Warnings ------------------------------- Clang provides a number of ways to control which code constructs cause it to emit errors and warning messages, and how they are displayed to the console. Controlling How Clang Displays Diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ When Clang emits a diagnostic, it includes rich information in the output, and gives you fine-grain control over which information is printed. Clang has the ability to print this information, and these are the options that control it: #. A file/line/column indicator that shows exactly where the diagnostic occurs in your code [:ref:`-fshow-column `, :ref:`-fshow-source-location `]. #. A categorization of the diagnostic as a note, warning, error, or fatal error. #. A text string that describes what the problem is. #. An option that indicates how to control the diagnostic (for diagnostics that support it) [:ref:`-fdiagnostics-show-option `]. #. A :ref:`high-level category ` for the diagnostic for clients that want to group diagnostics by class (for diagnostics that support it) [:ref:`-fdiagnostics-show-category `]. #. The line of source code that the issue occurs on, along with a caret and ranges that indicate the important locations [:ref:`-fcaret-diagnostics `]. #. "FixIt" information, which is a concise explanation of how to fix the problem (when Clang is certain it knows) [:ref:`-fdiagnostics-fixit-info `]. #. A machine-parsable representation of the ranges involved (off by default) [:ref:`-fdiagnostics-print-source-range-info `]. For more information please see :ref:`Formatting of Diagnostics `. Diagnostic Mappings ^^^^^^^^^^^^^^^^^^^ All diagnostics are mapped into one of these 6 classes: - Ignored - Note - Remark - Warning - Error - Fatal .. _diagnostics_categories: Diagnostic Categories ^^^^^^^^^^^^^^^^^^^^^ Though not shown by default, diagnostics may each be associated with a high-level category. This category is intended to make it possible to triage builds that produce a large number of errors or warnings in a grouped way. Categories are not shown by default, but they can be turned on with the :ref:`-fdiagnostics-show-category ` option. When set to "``name``", the category is printed textually in the diagnostic output. When it is set to "``id``", a category number is printed. The mapping of category names to category id's can be obtained by running '``clang --print-diagnostic-categories``'. Controlling Diagnostics via Command Line Flags ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TODO: -W flags, -pedantic, etc .. _pragma_gcc_diagnostic: Controlling Diagnostics via Pragmas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clang can also control what diagnostics are enabled through the use of pragmas in the source code. This is useful for turning off specific warnings in a section of source code. Clang supports GCC's pragma for compatibility with existing source code, as well as several extensions. The pragma may control any warning that can be used from the command line. Warnings may be set to ignored, warning, error, or fatal. The following example code will tell Clang or GCC to ignore the -Wall warnings: .. code-block:: c #pragma GCC diagnostic ignored "-Wall" In addition to all of the functionality provided by GCC's pragma, Clang also allows you to push and pop the current warning state. This is particularly useful when writing a header file that will be compiled by other people, because you don't know what warning flags they build with. In the below example :option:`-Wextra-tokens` is ignored for only a single line of code, after which the diagnostics return to whatever state had previously existed. .. code-block:: c #if foo #endif foo // warning: extra tokens at end of #endif directive #pragma clang diagnostic ignored "-Wextra-tokens" #if foo #endif foo // no warning #pragma clang diagnostic pop The push and pop pragmas will save and restore the full diagnostic state of the compiler, regardless of how it was set. That means that it is possible to use push and pop around GCC compatible diagnostics and Clang will push and pop them appropriately, while GCC will ignore the pushes and pops as unknown pragmas. It should be noted that while Clang supports the GCC pragma, Clang and GCC do not support the exact same set of warnings, so even when using GCC compatible #pragmas there is no guarantee that they will have identical behaviour on both compilers. In addition to controlling warnings and errors generated by the compiler, it is possible to generate custom warning and error messages through the following pragmas: .. code-block:: c // The following will produce warning messages #pragma message "some diagnostic message" #pragma GCC warning "TODO: replace deprecated feature" // The following will produce an error message #pragma GCC error "Not supported" These pragmas operate similarly to the ``#warning`` and ``#error`` preprocessor directives, except that they may also be embedded into preprocessor macros via the C99 ``_Pragma`` operator, for example: .. code-block:: c #define STR(X) #X #define DEFER(M,...) M(__VA_ARGS__) #define CUSTOM_ERROR(X) _Pragma(STR(GCC error(X " at line " DEFER(STR,__LINE__)))) CUSTOM_ERROR("Feature not available"); Controlling Diagnostics in System Headers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warnings are suppressed when they occur in system headers. By default, an included file is treated as a system header if it is found in an include path specified by ``-isystem``, but this can be overridden in several ways. The ``system_header`` pragma can be used to mark the current file as being a system header. No warnings will be produced from the location of the pragma onwards within the same file. .. code-block:: c #if foo #endif foo // warning: extra tokens at end of #endif directive #pragma clang system_header #if foo #endif foo // no warning The `--system-header-prefix=` and `--no-system-header-prefix=` command-line arguments can be used to override whether subsets of an include path are treated as system headers. When the name in a ``#include`` directive is found within a header search path and starts with a system prefix, the header is treated as a system header. The last prefix on the command-line which matches the specified header name takes precedence. For instance: .. code-block:: console $ clang -Ifoo -isystem bar --system-header-prefix=x/ \ --no-system-header-prefix=x/y/ Here, ``#include "x/a.h"`` is treated as including a system header, even if the header is found in ``foo``, and ``#include "x/y/b.h"`` is treated as not including a system header, even if the header is found in ``bar``. A ``#include`` directive which finds a file relative to the current directory is treated as including a system header if the including file is treated as a system header. .. _diagnostics_enable_everything: Enabling All Diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In addition to the traditional ``-W`` flags, one can enable **all** diagnostics by passing :option:`-Weverything`. This works as expected with :option:`-Werror`, and also includes the warnings from :option:`-pedantic`. Note that when combined with :option:`-w` (which disables all warnings), that flag wins. Controlling Static Analyzer Diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ While not strictly part of the compiler, the diagnostics from Clang's `static analyzer `_ can also be influenced by the user via changes to the source code. See the available `annotations `_ and the analyzer's `FAQ page `_ for more information. .. _usersmanual-precompiled-headers: Precompiled Headers ------------------- `Precompiled headers `__ are a general approach employed by many compilers to reduce compilation time. The underlying motivation of the approach is that it is common for the same (and often large) header files to be included by multiple source files. Consequently, compile times can often be greatly improved by caching some of the (redundant) work done by a compiler to process headers. Precompiled header files, which represent one of many ways to implement this optimization, are literally files that represent an on-disk cache that contains the vital information necessary to reduce some of the work needed to process a corresponding header file. While details of precompiled headers vary between compilers, precompiled headers have been shown to be highly effective at speeding up program compilation on systems with very large system headers (e.g., Mac OS X). Generating a PCH File ^^^^^^^^^^^^^^^^^^^^^ To generate a PCH file using Clang, one invokes Clang with the `-x -header` option. This mirrors the interface in GCC for generating PCH files: .. code-block:: console $ gcc -x c-header test.h -o test.h.gch $ clang -x c-header test.h -o test.h.pch Using a PCH File ^^^^^^^^^^^^^^^^ A PCH file can then be used as a prefix header when a :option:`-include` option is passed to ``clang``: .. code-block:: console $ clang -include test.h test.c -o test The ``clang`` driver will first check if a PCH file for ``test.h`` is available; if so, the contents of ``test.h`` (and the files it includes) will be processed from the PCH file. Otherwise, Clang falls back to directly processing the content of ``test.h``. This mirrors the behavior of GCC. .. note:: Clang does *not* automatically use PCH files for headers that are directly included within a source file. For example: .. code-block:: console $ clang -x c-header test.h -o test.h.pch $ cat test.c #include "test.h" $ clang test.c -o test In this example, ``clang`` will not automatically use the PCH file for ``test.h`` since ``test.h`` was included directly in the source file and not specified on the command line using :option:`-include`. Relocatable PCH Files ^^^^^^^^^^^^^^^^^^^^^ It is sometimes necessary to build a precompiled header from headers that are not yet in their final, installed locations. For example, one might build a precompiled header within the build tree that is then meant to be installed alongside the headers. Clang permits the creation of "relocatable" precompiled headers, which are built with a given path (into the build directory) and can later be used from an installed location. To build a relocatable precompiled header, place your headers into a subdirectory whose structure mimics the installed location. For example, if you want to build a precompiled header for the header ``mylib.h`` that will be installed into ``/usr/include``, create a subdirectory ``build/usr/include`` and place the header ``mylib.h`` into that subdirectory. If ``mylib.h`` depends on other headers, then they can be stored within ``build/usr/include`` in a way that mimics the installed location. Building a relocatable precompiled header requires two additional arguments. First, pass the ``--relocatable-pch`` flag to indicate that the resulting PCH file should be relocatable. Second, pass `-isysroot /path/to/build`, which makes all includes for your library relative to the build directory. For example: .. code-block:: console # clang -x c-header --relocatable-pch -isysroot /path/to/build /path/to/build/mylib.h mylib.h.pch When loading the relocatable PCH file, the various headers used in the PCH file are found from the system header root. For example, ``mylib.h`` can be found in ``/usr/include/mylib.h``. If the headers are installed in some other system root, the `-isysroot` option can be used provide a different system root from which the headers will be based. For example, `-isysroot /Developer/SDKs/MacOSX10.4u.sdk` will look for ``mylib.h`` in ``/Developer/SDKs/MacOSX10.4u.sdk/usr/include/mylib.h``. Relocatable precompiled headers are intended to be used in a limited number of cases where the compilation environment is tightly controlled and the precompiled header cannot be generated after headers have been installed. .. _controlling-code-generation: Controlling Code Generation --------------------------- Clang provides a number of ways to control code generation. The options are listed below. **-f[no-]sanitize=check1,check2,...** Turn on runtime checks for various forms of undefined or suspicious behavior. This option controls whether Clang adds runtime checks for various forms of undefined or suspicious behavior, and is disabled by default. If a check fails, a diagnostic message is produced at runtime explaining the problem. The main checks are: - .. _opt_fsanitize_address: ``-fsanitize=address``: :doc:`AddressSanitizer`, a memory error detector. - .. _opt_fsanitize_thread: ``-fsanitize=thread``: :doc:`ThreadSanitizer`, a data race detector. - .. _opt_fsanitize_memory: ``-fsanitize=memory``: :doc:`MemorySanitizer`, a detector of uninitialized reads. Requires instrumentation of all program code. - .. _opt_fsanitize_undefined: ``-fsanitize=undefined``: :doc:`UndefinedBehaviorSanitizer`, a fast and compatible undefined behavior checker. - ``-fsanitize=dataflow``: :doc:`DataFlowSanitizer`, a general data flow analysis. - ``-fsanitize=cfi``: :doc:`control flow integrity ` checks. Requires ``-flto``. - ``-fsanitize=safe-stack``: :doc:`safe stack ` protection against stack-based memory corruption errors. There are more fine-grained checks available: see the :ref:`list ` of specific kinds of undefined behavior that can be detected and the :ref:`list ` of control flow integrity schemes. The ``-fsanitize=`` argument must also be provided when linking, in order to link to the appropriate runtime library. It is not possible to combine more than one of the ``-fsanitize=address``, ``-fsanitize=thread``, and ``-fsanitize=memory`` checkers in the same program. **-f[no-]sanitize-recover=check1,check2,...** **-f[no-]sanitize-recover=all** Controls which checks enabled by ``-fsanitize=`` flag are non-fatal. If the check is fatal, program will halt after the first error of this kind is detected and error report is printed. By default, non-fatal checks are those enabled by :doc:`UndefinedBehaviorSanitizer`, except for ``-fsanitize=return`` and ``-fsanitize=unreachable``. Some sanitizers may not support recovery (or not support it by default e.g. :doc:`AddressSanitizer`), and always crash the program after the issue is detected. Note that the ``-fsanitize-trap`` flag has precedence over this flag. This means that if a check has been configured to trap elsewhere on the command line, or if the check traps by default, this flag will not have any effect unless that sanitizer's trapping behavior is disabled with ``-fno-sanitize-trap``. For example, if a command line contains the flags ``-fsanitize=undefined -fsanitize-trap=undefined``, the flag ``-fsanitize-recover=alignment`` will have no effect on its own; it will need to be accompanied by ``-fno-sanitize-trap=alignment``. **-f[no-]sanitize-trap=check1,check2,...** Controls which checks enabled by the ``-fsanitize=`` flag trap. This option is intended for use in cases where the sanitizer runtime cannot be used (for instance, when building libc or a kernel module), or where the binary size increase caused by the sanitizer runtime is a concern. This flag is only compatible with :doc:`control flow integrity ` schemes and :doc:`UndefinedBehaviorSanitizer` checks other than ``vptr``. If this flag is supplied together with ``-fsanitize=undefined``, the ``vptr`` sanitizer will be implicitly disabled. This flag is enabled by default for sanitizers in the ``cfi`` group. .. option:: -fsanitize-blacklist=/path/to/blacklist/file Disable or modify sanitizer checks for objects (source files, functions, variables, types) listed in the file. See :doc:`SanitizerSpecialCaseList` for file format description. .. option:: -fno-sanitize-blacklist Don't use blacklist file, if it was specified earlier in the command line. **-f[no-]sanitize-coverage=[type,features,...]** Enable simple code coverage in addition to certain sanitizers. See :doc:`SanitizerCoverage` for more details. **-f[no-]sanitize-stats** Enable simple statistics gathering for the enabled sanitizers. See :doc:`SanitizerStats` for more details. .. option:: -fsanitize-undefined-trap-on-error Deprecated alias for ``-fsanitize-trap=undefined``. .. option:: -fsanitize-cfi-cross-dso Enable cross-DSO control flow integrity checks. This flag modifies the behavior of sanitizers in the ``cfi`` group to allow checking of cross-DSO virtual and indirect calls. .. option:: -fstrict-vtable-pointers Enable optimizations based on the strict rules for overwriting polymorphic C++ objects, i.e. the vptr is invariant during an object's lifetime. This enables better devirtualization. Turned off by default, because it is still experimental. .. option:: -ffast-math Enable fast-math mode. This defines the ``__FAST_MATH__`` preprocessor macro, and lets the compiler make aggressive, potentially-lossy assumptions about floating-point math. These include: * Floating-point math obeys regular algebraic rules for real numbers (e.g. ``+`` and ``*`` are associative, ``x/y == x * (1/y)``, and ``(a + b) * c == a * c + b * c``), * operands to floating-point operations are not equal to ``NaN`` and ``Inf``, and * ``+0`` and ``-0`` are interchangeable. .. option:: -fdenormal-fp-math=[values] Select which denormal numbers the code is permitted to require. Valid values are: ``ieee``, ``preserve-sign``, and ``positive-zero``, which correspond to IEEE 754 denormal numbers, the sign of a flushed-to-zero number is preserved in the sign of 0, denormals are flushed to positive zero, respectively. .. option:: -fwhole-program-vtables Enable whole-program vtable optimizations, such as single-implementation devirtualization and virtual constant propagation, for classes with :doc:`hidden LTO visibility `. Requires ``-flto``. .. option:: -fno-assume-sane-operator-new Don't assume that the C++'s new operator is sane. This option tells the compiler to do not assume that C++'s global new operator will always return a pointer that does not alias any other pointer when the function returns. .. option:: -ftrap-function=[name] Instruct code generator to emit a function call to the specified function name for ``__builtin_trap()``. LLVM code generator translates ``__builtin_trap()`` to a trap instruction if it is supported by the target ISA. Otherwise, the builtin is translated into a call to ``abort``. If this option is set, then the code generator will always lower the builtin to a call to the specified function regardless of whether the target ISA has a trap instruction. This option is useful for environments (e.g. deeply embedded) where a trap cannot be properly handled, or when some custom behavior is desired. .. option:: -ftls-model=[model] Select which TLS model to use. Valid values are: ``global-dynamic``, ``local-dynamic``, ``initial-exec`` and ``local-exec``. The default value is ``global-dynamic``. The compiler may use a different model if the selected model is not supported by the target, or if a more efficient model can be used. The TLS model can be overridden per variable using the ``tls_model`` attribute. .. option:: -femulated-tls Select emulated TLS model, which overrides all -ftls-model choices. In emulated TLS mode, all access to TLS variables are converted to calls to __emutls_get_address in the runtime library. .. option:: -mhwdiv=[values] Select the ARM modes (arm or thumb) that support hardware division instructions. Valid values are: ``arm``, ``thumb`` and ``arm,thumb``. This option is used to indicate which mode (arm or thumb) supports hardware division instructions. This only applies to the ARM architecture. .. option:: -m[no-]crc Enable or disable CRC instructions. This option is used to indicate whether CRC instructions are to be generated. This only applies to the ARM architecture. CRC instructions are enabled by default on ARMv8. .. option:: -mgeneral-regs-only Generate code which only uses the general purpose registers. This option restricts the generated code to use general registers only. This only applies to the AArch64 architecture. .. option:: -mcompact-branches=[values] Control the usage of compact branches for MIPSR6. Valid values are: ``never``, ``optimal`` and ``always``. The default value is ``optimal`` which generates compact branches when a delay slot cannot be filled. ``never`` disables the usage of compact branches and ``always`` generates compact branches whenever possible. **-f[no-]max-type-align=[number]** Instruct the code generator to not enforce a higher alignment than the given number (of bytes) when accessing memory via an opaque pointer or reference. This cap is ignored when directly accessing a variable or when the pointee type has an explicit “aligned” attribute. The value should usually be determined by the properties of the system allocator. Some builtin types, especially vector types, have very high natural alignments; when working with values of those types, Clang usually wants to use instructions that take advantage of that alignment. However, many system allocators do not promise to return memory that is more than 8-byte or 16-byte-aligned. Use this option to limit the alignment that the compiler can assume for an arbitrary pointer, which may point onto the heap. This option does not affect the ABI alignment of types; the layout of structs and unions and the value returned by the alignof operator remain the same. This option can be overridden on a case-by-case basis by putting an explicit “aligned” alignment on a struct, union, or typedef. For example: .. code-block:: console #include // Make an aligned typedef of the AVX-512 16-int vector type. typedef __v16si __aligned_v16si __attribute__((aligned(64))); void initialize_vector(__aligned_v16si *v) { // The compiler may assume that ‘v’ is 64-byte aligned, regardless of the // value of -fmax-type-align. } Profile Guided Optimization --------------------------- Profile information enables better optimization. For example, knowing that a branch is taken very frequently helps the compiler make better decisions when ordering basic blocks. Knowing that a function ``foo`` is called more frequently than another function ``bar`` helps the inliner. Clang supports profile guided optimization with two different kinds of profiling. A sampling profiler can generate a profile with very low runtime overhead, or you can build an instrumented version of the code that collects more detailed profile information. Both kinds of profiles can provide execution counts for instructions in the code and information on branches taken and function invocation. Regardless of which kind of profiling you use, be careful to collect profiles by running your code with inputs that are representative of the typical behavior. Code that is not exercised in the profile will be optimized as if it is unimportant, and the compiler may make poor optimization choices for code that is disproportionately used while profiling. Differences Between Sampling and Instrumentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Although both techniques are used for similar purposes, there are important differences between the two: 1. Profile data generated with one cannot be used by the other, and there is no conversion tool that can convert one to the other. So, a profile generated via ``-fprofile-instr-generate`` must be used with ``-fprofile-instr-use``. Similarly, sampling profiles generated by external profilers must be converted and used with ``-fprofile-sample-use``. 2. Instrumentation profile data can be used for code coverage analysis and optimization. 3. Sampling profiles can only be used for optimization. They cannot be used for code coverage analysis. Although it would be technically possible to use sampling profiles for code coverage, sample-based profiles are too coarse-grained for code coverage purposes; it would yield poor results. 4. Sampling profiles must be generated by an external tool. The profile generated by that tool must then be converted into a format that can be read by LLVM. The section on sampling profilers describes one of the supported sampling profile formats. Using Sampling Profilers ^^^^^^^^^^^^^^^^^^^^^^^^ Sampling profilers are used to collect runtime information, such as hardware counters, while your application executes. They are typically very efficient and do not incur a large runtime overhead. The sample data collected by the profiler can be used during compilation to determine what the most executed areas of the code are. Using the data from a sample profiler requires some changes in the way a program is built. Before the compiler can use profiling information, the code needs to execute under the profiler. The following is the usual build cycle when using sample profilers for optimization: 1. Build the code with source line table information. You can use all the usual build flags that you always build your application with. The only requirement is that you add ``-gline-tables-only`` or ``-g`` to the command line. This is important for the profiler to be able to map instructions back to source line locations. .. code-block:: console $ clang++ -O2 -gline-tables-only code.cc -o code 2. Run the executable under a sampling profiler. The specific profiler you use does not really matter, as long as its output can be converted into the format that the LLVM optimizer understands. Currently, there exists a conversion tool for the Linux Perf profiler (https://perf.wiki.kernel.org/), so these examples assume that you are using Linux Perf to profile your code. .. code-block:: console $ perf record -b ./code Note the use of the ``-b`` flag. This tells Perf to use the Last Branch Record (LBR) to record call chains. While this is not strictly required, it provides better call information, which improves the accuracy of the profile data. 3. Convert the collected profile data to LLVM's sample profile format. This is currently supported via the AutoFDO converter ``create_llvm_prof``. It is available at http://github.com/google/autofdo. Once built and installed, you can convert the ``perf.data`` file to LLVM using the command: .. code-block:: console $ create_llvm_prof --binary=./code --out=code.prof This will read ``perf.data`` and the binary file ``./code`` and emit the profile data in ``code.prof``. Note that if you ran ``perf`` without the ``-b`` flag, you need to use ``--use_lbr=false`` when calling ``create_llvm_prof``. 4. Build the code again using the collected profile. This step feeds the profile back to the optimizers. This should result in a binary that executes faster than the original one. Note that you are not required to build the code with the exact same arguments that you used in the first step. The only requirement is that you build the code with ``-gline-tables-only`` and ``-fprofile-sample-use``. .. code-block:: console $ clang++ -O2 -gline-tables-only -fprofile-sample-use=code.prof code.cc -o code Sample Profile Formats """""""""""""""""""""" Since external profilers generate profile data in a variety of custom formats, the data generated by the profiler must be converted into a format that can be read by the backend. LLVM supports three different sample profile formats: 1. ASCII text. This is the easiest one to generate. The file is divided into sections, which correspond to each of the functions with profile information. The format is described below. It can also be generated from the binary or gcov formats using the ``llvm-profdata`` tool. 2. Binary encoding. This uses a more efficient encoding that yields smaller profile files. This is the format generated by the ``create_llvm_prof`` tool in http://github.com/google/autofdo. 3. GCC encoding. This is based on the gcov format, which is accepted by GCC. It is only interesting in environments where GCC and Clang co-exist. This encoding is only generated by the ``create_gcov`` tool in http://github.com/google/autofdo. It can be read by LLVM and ``llvm-profdata``, but it cannot be generated by either. If you are using Linux Perf to generate sampling profiles, you can use the conversion tool ``create_llvm_prof`` described in the previous section. Otherwise, you will need to write a conversion tool that converts your profiler's native format into one of these three. Sample Profile Text Format """""""""""""""""""""""""" This section describes the ASCII text format for sampling profiles. It is, arguably, the easiest one to generate. If you are interested in generating any of the other two, consult the ``ProfileData`` library in in LLVM's source tree (specifically, ``include/llvm/ProfileData/SampleProfReader.h``). .. code-block:: console function1:total_samples:total_head_samples offset1[.discriminator]: number_of_samples [fn1:num fn2:num ... ] offset2[.discriminator]: number_of_samples [fn3:num fn4:num ... ] ... offsetN[.discriminator]: number_of_samples [fn5:num fn6:num ... ] offsetA[.discriminator]: fnA:num_of_total_samples offsetA1[.discriminator]: number_of_samples [fn7:num fn8:num ... ] offsetA1[.discriminator]: number_of_samples [fn9:num fn10:num ... ] offsetB[.discriminator]: fnB:num_of_total_samples offsetB1[.discriminator]: number_of_samples [fn11:num fn12:num ... ] This is a nested tree in which the identation represents the nesting level of the inline stack. There are no blank lines in the file. And the spacing within a single line is fixed. Additional spaces will result in an error while reading the file. Any line starting with the '#' character is completely ignored. Inlined calls are represented with indentation. The Inline stack is a stack of source locations in which the top of the stack represents the leaf function, and the bottom of the stack represents the actual symbol to which the instruction belongs. Function names must be mangled in order for the profile loader to match them in the current translation unit. The two numbers in the function header specify how many total samples were accumulated in the function (first number), and the total number of samples accumulated in the prologue of the function (second number). This head sample count provides an indicator of how frequently the function is invoked. There are two types of lines in the function body. - Sampled line represents the profile information of a source location. ``offsetN[.discriminator]: number_of_samples [fn5:num fn6:num ... ]`` - Callsite line represents the profile information of an inlined callsite. ``offsetA[.discriminator]: fnA:num_of_total_samples`` Each sampled line may contain several items. Some are optional (marked below): a. Source line offset. This number represents the line number in the function where the sample was collected. The line number is always relative to the line where symbol of the function is defined. So, if the function has its header at line 280, the offset 13 is at line 293 in the file. Note that this offset should never be a negative number. This could happen in cases like macros. The debug machinery will register the line number at the point of macro expansion. So, if the macro was expanded in a line before the start of the function, the profile converter should emit a 0 as the offset (this means that the optimizers will not be able to associate a meaningful weight to the instructions in the macro). b. [OPTIONAL] Discriminator. This is used if the sampled program was compiled with DWARF discriminator support (http://wiki.dwarfstd.org/index.php?title=Path_Discriminators). DWARF discriminators are unsigned integer values that allow the compiler to distinguish between multiple execution paths on the same source line location. For example, consider the line of code ``if (cond) foo(); else bar();``. If the predicate ``cond`` is true 80% of the time, then the edge into function ``foo`` should be considered to be taken most of the time. But both calls to ``foo`` and ``bar`` are at the same source line, so a sample count at that line is not sufficient. The compiler needs to know which part of that line is taken more frequently. This is what discriminators provide. In this case, the calls to ``foo`` and ``bar`` will be at the same line, but will have different discriminator values. This allows the compiler to correctly set edge weights into ``foo`` and ``bar``. c. Number of samples. This is an integer quantity representing the number of samples collected by the profiler at this source location. d. [OPTIONAL] Potential call targets and samples. If present, this line contains a call instruction. This models both direct and number of samples. For example, .. code-block:: console 130: 7 foo:3 bar:2 baz:7 The above means that at relative line offset 130 there is a call instruction that calls one of ``foo()``, ``bar()`` and ``baz()``, with ``baz()`` being the relatively more frequently called target. As an example, consider a program with the call chain ``main -> foo -> bar``. When built with optimizations enabled, the compiler may inline the calls to ``bar`` and ``foo`` inside ``main``. The generated profile could then be something like this: .. code-block:: console main:35504:0 1: _Z3foov:35504 2: _Z32bari:31977 1.1: 31977 2: 0 This profile indicates that there were a total of 35,504 samples collected in main. All of those were at line 1 (the call to ``foo``). Of those, 31,977 were spent inside the body of ``bar``. The last line of the profile (``2: 0``) corresponds to line 2 inside ``main``. No samples were collected there. Profiling with Instrumentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clang also supports profiling via instrumentation. This requires building a special instrumented version of the code and has some runtime overhead during the profiling, but it provides more detailed results than a sampling profiler. It also provides reproducible results, at least to the extent that the code behaves consistently across runs. Here are the steps for using profile guided optimization with instrumentation: 1. Build an instrumented version of the code by compiling and linking with the ``-fprofile-instr-generate`` option. .. code-block:: console $ clang++ -O2 -fprofile-instr-generate code.cc -o code 2. Run the instrumented executable with inputs that reflect the typical usage. By default, the profile data will be written to a ``default.profraw`` file in the current directory. You can override that default by using option ``-fprofile-instr-generate=`` or by setting the ``LLVM_PROFILE_FILE`` environment variable to specify an alternate file. If non-default file name is specified by both the environment variable and the command line option, the environment variable takes precedence. The file name pattern specified can include different modifiers: ``%p``, ``%h``, and ``%m``. Any instance of ``%p`` in that file name will be replaced by the process ID, so that you can easily distinguish the profile output from multiple runs. .. code-block:: console $ LLVM_PROFILE_FILE="code-%p.profraw" ./code The modifier ``%h`` can be used in scenarios where the same instrumented binary is run in multiple different host machines dumping profile data to a shared network based storage. The ``%h`` specifier will be substituted with the hostname so that profiles collected from different hosts do not clobber each other. While the use of ``%p`` specifier can reduce the likelihood for the profiles dumped from different processes to clobber each other, such clobbering can still happen because of the ``pid`` re-use by the OS. Another side-effect of using ``%p`` is that the storage requirement for raw profile data files is greatly increased. To avoid issues like this, the ``%m`` specifier can used in the profile name. When this specifier is used, the profiler runtime will substitute ``%m`` with a unique integer identifier associated with the instrumented binary. Additionally, multiple raw profiles dumped from different processes that share a file system (can be on different hosts) will be automatically merged by the profiler runtime during the dumping. If the program links in multiple instrumented shared libraries, each library will dump the profile data into its own profile data file (with its unique integer id embedded in the profile name). Note that the merging enabled by ``%m`` is for raw profile data generated by profiler runtime. The resulting merged "raw" profile data file still needs to be converted to a different format expected by the compiler ( see step 3 below). .. code-block:: console $ LLVM_PROFILE_FILE="code-%m.profraw" ./code 3. Combine profiles from multiple runs and convert the "raw" profile format to the input expected by clang. Use the ``merge`` command of the ``llvm-profdata`` tool to do this. .. code-block:: console $ llvm-profdata merge -output=code.profdata code-*.profraw Note that this step is necessary even when there is only one "raw" profile, since the merge operation also changes the file format. 4. Build the code again using the ``-fprofile-instr-use`` option to specify the collected profile data. .. code-block:: console $ clang++ -O2 -fprofile-instr-use=code.profdata code.cc -o code You can repeat step 4 as often as you like without regenerating the profile. As you make changes to your code, clang may no longer be able to use the profile data. It will warn you when this happens. Profile generation using an alternative instrumentation method can be controlled by the GCC-compatible flags ``-fprofile-generate`` and ``-fprofile-use``. Although these flags are semantically equivalent to their GCC counterparts, they *do not* handle GCC-compatible profiles. They are only meant to implement GCC's semantics with respect to profile creation and use. .. option:: -fprofile-generate[=] The ``-fprofile-generate`` and ``-fprofile-generate=`` flags will use an alterantive instrumentation method for profile generation. When given a directory name, it generates the profile file ``default_%m.profraw`` in the directory named ``dirname`` if specified. If ``dirname`` does not exist, it will be created at runtime. ``%m`` specifier will be substibuted with a unique id documented in step 2 above. In other words, with ``-fprofile-generate[=]`` option, the "raw" profile data automatic merging is turned on by default, so there will no longer any risk of profile clobbering from different running processes. For example, .. code-block:: console $ clang++ -O2 -fprofile-generate=yyy/zzz code.cc -o code When ``code`` is executed, the profile will be written to the file ``yyy/zzz/default_xxxx.profraw``. To generate the profile data file with the compiler readable format, the ``llvm-profdata`` tool can be used with the profile directory as the input: .. code-block:: console $ llvm-profdata merge -output=code.profdata yyy/zzz/ If the user wants to turn off the auto-merging feature, or simply override the the profile dumping path specified at command line, the environment variable ``LLVM_PROFILE_FILE`` can still be used to override the directory and filename for the profile file at runtime. .. option:: -fprofile-use[=] Without any other arguments, ``-fprofile-use`` behaves identically to ``-fprofile-instr-use``. Otherwise, if ``pathname`` is the full path to a profile file, it reads from that file. If ``pathname`` is a directory name, it reads from ``pathname/default.profdata``. Disabling Instrumentation ^^^^^^^^^^^^^^^^^^^^^^^^^ In certain situations, it may be useful to disable profile generation or use for specific files in a build, without affecting the main compilation flags used for the other files in the project. In these cases, you can use the flag ``-fno-profile-instr-generate`` (or ``-fno-profile-generate``) to disable profile generation, and ``-fno-profile-instr-use`` (or ``-fno-profile-use``) to disable profile use. Note that these flags should appear after the corresponding profile flags to have an effect. Controlling Debug Information ----------------------------- Controlling Size of Debug Information ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Debug info kind generated by Clang can be set by one of the flags listed below. If multiple flags are present, the last one is used. .. option:: -g0 Don't generate any debug info (default). .. option:: -gline-tables-only Generate line number tables only. This kind of debug info allows to obtain stack traces with function names, file names and line numbers (by such tools as ``gdb`` or ``addr2line``). It doesn't contain any other data (e.g. description of local variables or function parameters). .. option:: -fstandalone-debug Clang supports a number of optimizations to reduce the size of debug information in the binary. They work based on the assumption that the debug type information can be spread out over multiple compilation units. For instance, Clang will not emit type definitions for types that are not needed by a module and could be replaced with a forward declaration. Further, Clang will only emit type info for a dynamic C++ class in the module that contains the vtable for the class. The **-fstandalone-debug** option turns off these optimizations. This is useful when working with 3rd-party libraries that don't come with debug information. Note that Clang will never emit type information for types that are not referenced at all by the program. .. option:: -fno-standalone-debug On Darwin **-fstandalone-debug** is enabled by default. The **-fno-standalone-debug** option can be used to get to turn on the vtable-based optimization described above. .. option:: -g Generate complete debug info. Controlling Debugger "Tuning" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ While Clang generally emits standard DWARF debug info (http://dwarfstd.org), different debuggers may know how to take advantage of different specific DWARF features. You can "tune" the debug info for one of several different debuggers. .. option:: -ggdb, -glldb, -gsce Tune the debug info for the ``gdb``, ``lldb``, or Sony PlayStation\ |reg| debugger, respectively. Each of these options implies **-g**. (Therefore, if you want both **-gline-tables-only** and debugger tuning, the tuning option must come first.) Comment Parsing Options ----------------------- Clang parses Doxygen and non-Doxygen style documentation comments and attaches them to the appropriate declaration nodes. By default, it only parses Doxygen-style comments and ignores ordinary comments starting with ``//`` and ``/*``. .. option:: -Wdocumentation Emit warnings about use of documentation comments. This warning group is off by default. This includes checking that ``\param`` commands name parameters that actually present in the function signature, checking that ``\returns`` is used only on functions that actually return a value etc. .. option:: -Wno-documentation-unknown-command Don't warn when encountering an unknown Doxygen command. .. option:: -fparse-all-comments Parse all comments as documentation comments (including ordinary comments starting with ``//`` and ``/*``). .. option:: -fcomment-block-commands=[commands] Define custom documentation commands as block commands. This allows Clang to construct the correct AST for these custom commands, and silences warnings about unknown commands. Several commands must be separated by a comma *without trailing space*; e.g. ``-fcomment-block-commands=foo,bar`` defines custom commands ``\foo`` and ``\bar``. It is also possible to use ``-fcomment-block-commands`` several times; e.g. ``-fcomment-block-commands=foo -fcomment-block-commands=bar`` does the same as above. .. _c: C Language Features =================== The support for standard C in clang is feature-complete except for the C99 floating-point pragmas. Extensions supported by clang ----------------------------- See :doc:`LanguageExtensions`. Differences between various standard modes ------------------------------------------ clang supports the -std option, which changes what language mode clang uses. The supported modes for C are c89, gnu89, c94, c99, gnu99, c11, gnu11, and various aliases for those modes. If no -std option is specified, clang defaults to gnu11 mode. Many C99 and C11 features are supported in earlier modes as a conforming extension, with a warning. Use ``-pedantic-errors`` to request an error if a feature from a later standard revision is used in an earlier mode. Differences between all ``c*`` and ``gnu*`` modes: - ``c*`` modes define "``__STRICT_ANSI__``". - Target-specific defines not prefixed by underscores, like "linux", are defined in ``gnu*`` modes. - Trigraphs default to being off in ``gnu*`` modes; they can be enabled by the -trigraphs option. - The parser recognizes "asm" and "typeof" as keywords in ``gnu*`` modes; the variants "``__asm__``" and "``__typeof__``" are recognized in all modes. - The Apple "blocks" extension is recognized by default in ``gnu*`` modes on some platforms; it can be enabled in any mode with the "-fblocks" option. - Arrays that are VLA's according to the standard, but which can be constant folded by the frontend are treated as fixed size arrays. This occurs for things like "int X[(1, 2)];", which is technically a VLA. ``c*`` modes are strictly compliant and treat these as VLAs. Differences between ``*89`` and ``*99`` modes: - The ``*99`` modes default to implementing "inline" as specified in C99, while the ``*89`` modes implement the GNU version. This can be overridden for individual functions with the ``__gnu_inline__`` attribute. - Digraphs are not recognized in c89 mode. - The scope of names defined inside a "for", "if", "switch", "while", or "do" statement is different. (example: "``if ((struct x {int x;}*)0) {}``".) - ``__STDC_VERSION__`` is not defined in ``*89`` modes. - "inline" is not recognized as a keyword in c89 mode. - "restrict" is not recognized as a keyword in ``*89`` modes. - Commas are allowed in integer constant expressions in ``*99`` modes. - Arrays which are not lvalues are not implicitly promoted to pointers in ``*89`` modes. - Some warnings are different. Differences between ``*99`` and ``*11`` modes: - Warnings for use of C11 features are disabled. - ``__STDC_VERSION__`` is defined to ``201112L`` rather than ``199901L``. c94 mode is identical to c89 mode except that digraphs are enabled in c94 mode (FIXME: And ``__STDC_VERSION__`` should be defined!). GCC extensions not implemented yet ---------------------------------- clang tries to be compatible with gcc as much as possible, but some gcc extensions are not implemented yet: - clang does not support decimal floating point types (``_Decimal32`` and friends) or fixed-point types (``_Fract`` and friends); nobody has expressed interest in these features yet, so it's hard to say when they will be implemented. - clang does not support nested functions; this is a complex feature which is infrequently used, so it is unlikely to be implemented anytime soon. In C++11 it can be emulated by assigning lambda functions to local variables, e.g: .. code-block:: cpp auto const local_function = [&](int parameter) { // Do something }; ... local_function(1); - clang only supports global register variables when the register specified is non-allocatable (e.g. the stack pointer). Support for general global register variables is unlikely to be implemented soon because it requires additional LLVM backend support. - clang does not support static initialization of flexible array members. This appears to be a rarely used extension, but could be implemented pending user demand. - clang does not support ``__builtin_va_arg_pack``/``__builtin_va_arg_pack_len``. This is used rarely, but in some potentially interesting places, like the glibc headers, so it may be implemented pending user demand. Note that because clang pretends to be like GCC 4.2, and this extension was introduced in 4.3, the glibc headers will not try to use this extension with clang at the moment. - clang does not support the gcc extension for forward-declaring function parameters; this has not shown up in any real-world code yet, though, so it might never be implemented. This is not a complete list; if you find an unsupported extension missing from this list, please send an e-mail to cfe-dev. This list currently excludes C++; see :ref:`C++ Language Features `. Also, this list does not include bugs in mostly-implemented features; please see the `bug tracker `_ for known existing bugs (FIXME: Is there a section for bug-reporting guidelines somewhere?). Intentionally unsupported GCC extensions ---------------------------------------- - clang does not support the gcc extension that allows variable-length arrays in structures. This is for a few reasons: one, it is tricky to implement, two, the extension is completely undocumented, and three, the extension appears to be rarely used. Note that clang *does* support flexible array members (arrays with a zero or unspecified size at the end of a structure). - clang does not have an equivalent to gcc's "fold"; this means that clang doesn't accept some constructs gcc might accept in contexts where a constant expression is required, like "x-x" where x is a variable. - clang does not support ``__builtin_apply`` and friends; this extension is extremely obscure and difficult to implement reliably. .. _c_ms: Microsoft extensions -------------------- clang has support for many extensions from Microsoft Visual C++. To enable these extensions, use the ``-fms-extensions`` command-line option. This is the default for Windows targets. Clang does not implement every pragma or declspec provided by MSVC, but the popular ones, such as ``__declspec(dllexport)`` and ``#pragma comment(lib)`` are well supported. clang has a ``-fms-compatibility`` flag that makes clang accept enough invalid C++ to be able to parse most Microsoft headers. For example, it allows `unqualified lookup of dependent base class members `_, which is a common compatibility issue with clang. This flag is enabled by default for Windows targets. ``-fdelayed-template-parsing`` lets clang delay parsing of function template definitions until the end of a translation unit. This flag is enabled by default for Windows targets. For compatibility with existing code that compiles with MSVC, clang defines the ``_MSC_VER`` and ``_MSC_FULL_VER`` macros. These default to the values of 1800 and 180000000 respectively, making clang look like an early release of Visual C++ 2013. The ``-fms-compatibility-version=`` flag overrides these values. It accepts a dotted version tuple, such as 19.00.23506. Changing the MSVC compatibility version makes clang behave more like that version of MSVC. For example, ``-fms-compatibility-version=19`` will enable C++14 features and define ``char16_t`` and ``char32_t`` as builtin types. .. _cxx: C++ Language Features ===================== clang fully implements all of standard C++98 except for exported templates (which were removed in C++11), and all of standard C++11 and the current draft standard for C++1y. Controlling implementation limits --------------------------------- .. option:: -fbracket-depth=N Sets the limit for nested parentheses, brackets, and braces to N. The default is 256. .. option:: -fconstexpr-depth=N Sets the limit for recursive constexpr function invocations to N. The default is 512. .. option:: -ftemplate-depth=N Sets the limit for recursively nested template instantiations to N. The default is 256. .. option:: -foperator-arrow-depth=N Sets the limit for iterative calls to 'operator->' functions to N. The default is 256. .. _objc: Objective-C Language Features ============================= .. _objcxx: Objective-C++ Language Features =============================== .. _openmp: OpenMP Features =============== Clang supports all OpenMP 3.1 directives and clauses. In addition, some features of OpenMP 4.0 are supported. For example, ``#pragma omp simd``, ``#pragma omp for simd``, ``#pragma omp parallel for simd`` directives, extended set of atomic constructs, ``proc_bind`` clause for all parallel-based directives, ``depend`` clause for ``#pragma omp task`` directive (except for array sections), ``#pragma omp cancel`` and ``#pragma omp cancellation point`` directives, and ``#pragma omp taskgroup`` directive. Use `-fopenmp` to enable OpenMP. Support for OpenMP can be disabled with `-fno-openmp`. Controlling implementation limits --------------------------------- .. option:: -fopenmp-use-tls Controls code generation for OpenMP threadprivate variables. In presence of this option all threadprivate variables are generated the same way as thread local variables, using TLS support. If `-fno-openmp-use-tls` is provided or target does not support TLS, code generation for threadprivate variables relies on OpenMP runtime library. .. _opencl: OpenCL Features =============== Clang can be used to compile OpenCL kernels for execution on a device (e.g. GPU). It is possible to compile the kernel into a binary (e.g. for AMD or Nvidia targets) that can be uploaded to run directly on a device (e.g. using `clCreateProgramWithBinary `_) or into generic bitcode files loadable into other toolchains. Compiling to a binary using the default target from the installation can be done as follows: .. code-block:: console $ echo "kernel void k(){}" > test.cl $ clang test.cl Compiling for a specific target can be done by specifying the triple corresponding to the target, for example: .. code-block:: console $ clang -target nvptx64-unknown-unknown test.cl $ clang -target amdgcn-amd-amdhsa-opencl test.cl Compiling to bitcode can be done as follows: .. code-block:: console $ clang -c -emit-llvm test.cl This will produce a generic test.bc file that can be used in vendor toolchains to perform machine code generation. Clang currently supports OpenCL C language standards up to v2.0. OpenCL Specific Options ----------------------- Most of the OpenCL build options from `the specification v2.0 section 5.8.4 `_ are available. Examples: .. code-block:: console $ clang -cl-std=CL2.0 -cl-single-precision-constant test.cl Some extra options are available to support special OpenCL features. .. option:: -finclude-default-header Loads standard includes during compilations. By default OpenCL headers are not loaded and therefore standard library includes are not available. To load them automatically a flag has been added to the frontend (see also :ref:`the section on the OpenCL Header `): .. code-block:: console $ clang -Xclang -finclude-default-header test.cl Alternatively ``-include`` or ``-I`` followed by the path to the header location can be given manually. .. code-block:: console $ clang -I/lib/Headers/opencl-c.h test.cl In this case the kernel code should contain ``#include `` just as a regular C include. +.. _opencl_cl_ext: + .. option:: -cl-ext Disables support of OpenCL extensions. All OpenCL targets provide a list of extensions that they support. Clang allows to amend this using the ``-cl-ext`` flag with a comma-separated list of extensions prefixed with ``'+'`` or ``'-'``. The syntax: ``-cl-ext=<(['-'|'+'][,])+>``, where extensions can be either one of `the OpenCL specification extensions `_ or any known vendor extension. Alternatively, ``'all'`` can be used to enable or disable all known extensions. Example disabling double support for the 64-bit SPIR target: .. code-block:: console $ clang -cc1 -triple spir64-unknown-unknown -cl-ext=-cl_khr_fp64 test.cl Enabling all extensions except double support in R600 AMD GPU can be done using: .. code-block:: console $ clang -cc1 -triple r600-unknown-unknown -cl-ext=-all,+cl_khr_fp16 test.cl .. _opencl_fake_address_space_map: .. option:: -ffake-address-space-map Overrides the target address space map with a fake map. This allows adding explicit address space IDs to the bitcode for non-segmented memory architectures that don't have separate IDs for each of the OpenCL logical address spaces by default. Passing ``-ffake-address-space-map`` will add/override address spaces of the target compiled for with the following values: ``1-global``, ``2-constant``, ``3-local``, ``4-generic``. The private address space is represented by the absence of an address space attribute in the IR (see also :ref:`the section on the address space attribute `). .. code-block:: console $ clang -ffake-address-space-map test.cl Some other flags used for the compilation for C can also be passed while compiling for OpenCL, examples: ``-c``, ``-O<1-4|s>``, ``-o``, ``-emit-llvm``, etc. OpenCL Targets -------------- OpenCL targets are derived from the regular Clang target classes. The OpenCL specific parts of the target representation provide address space mapping as well as a set of supported extensions. Specific Targets ^^^^^^^^^^^^^^^^ There is a set of concrete HW architectures that OpenCL can be compiled for. - For AMD target: .. code-block:: console $ clang -target amdgcn-amd-amdhsa-opencl test.cl - For Nvidia architectures: .. code-block:: console $ clang -target nvptx64-unknown-unknown test.cl Generic Targets ^^^^^^^^^^^^^^^ - SPIR is available as a generic target to allow portable bitcode to be produced that can be used across GPU toolchains. The implementation follows `the SPIR specification `_. There are two flavors available for 32 and 64 bits. .. code-block:: console $ clang -target spir-unknown-unknown test.cl $ clang -target spir64-unknown-unknown test.cl All known OpenCL extensions are supported in the SPIR targets. Clang will generate SPIR v1.2 compatible IR for OpenCL versions up to 2.0 and SPIR v2.0 for OpenCL v2.0. - x86 is used by some implementations that are x86 compatible and currently remains for backwards compatibility (with older implementations prior to SPIR target support). For "non-SPMD" targets which cannot spawn multiple work-items on the fly using hardware, which covers practically all non-GPU devices such as CPUs and DSPs, additional processing is needed for the kernels to support multiple work-item execution. For this, a 3rd party toolchain, such as for example `POCL `_, can be used. This target does not support multiple memory segments and, therefore, the fake address space map can be added using the :ref:`-ffake-address-space-map ` flag. .. _opencl_header: OpenCL Header ------------- By default Clang will not include standard headers and therefore OpenCL builtin functions and some types (i.e. vectors) are unknown. The default CL header is, however, provided in the Clang installation and can be enabled by passing the ``-finclude-default-header`` flag to the Clang frontend. .. code-block:: console $ echo "bool is_wg_uniform(int i){return get_enqueued_local_size(i)==get_local_size(i);}" > test.cl $ clang -Xclang -finclude-default-header -cl-std=CL2.0 test.cl Because the header is very large and long to parse, PCH (:doc:`PCHInternals`) and modules (:doc:`Modules`) are used internally to improve the compilation speed. To enable modules for OpenCL: .. code-block:: console $ clang -target spir-unknown-unknown -c -emit-llvm -Xclang -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path= test.cl +OpenCL Extensions +----------------- + +All of the ``cl_khr_*`` extensions from `the official OpenCL specification +`_ +up to and including version 2.0 are available and set per target depending on the +support available in the specific architecture. + +It is possible to alter the default extensions setting per target using +``-cl-ext`` flag. (See :ref:`flags description ` for more details). + +Vendor extensions can be added flexibly by declaring the list of types and +functions associated with each extensions enclosed within the following +compiler pragma directives: + + .. code-block:: c + + #pragma OPENCL EXTENSION the_new_extension_name : begin + // declare types and functions associated with the extension here + #pragma OPENCL EXTENSION the_new_extension_name : end + +For example, parsing the following code adds ``my_t`` type and ``my_func`` +function to the custom ``my_ext`` extension. + + .. code-block:: c + + #pragma OPENCL EXTENSION my_ext : begin + typedef struct{ + int a; + }my_t; + void my_func(my_t); + #pragma OPENCL EXTENSION my_ext : end + +Declaring the same types in different vendor extensions is disallowed. + OpenCL Metadata --------------- Clang uses metadata to provide additional OpenCL semantics in IR needed for backends and OpenCL runtime. Each kernel will have function metadata attached to it, specifying the arguments. Kernel argument metadata is used to provide source level information for querying at runtime, for example using the `clGetKernelArgInfo `_ call. Note that ``-cl-kernel-arg-info`` enables more information about the original CL code to be added e.g. kernel parameter names will appear in the OpenCL metadata along with other information. The IDs used to encode the OpenCL's logical address spaces in the argument info metadata follows the SPIR address space mapping as defined in the SPIR specification `section 2.2 `_ OpenCL-Specific Attributes -------------------------- OpenCL support in Clang contains a set of attribute taken directly from the specification as well as additional attributes. See also :doc:`AttributeReference`. nosvm ^^^^^ Clang supports this attribute to comply to OpenCL v2.0 conformance, but it does not have any effect on the IR. For more details reffer to the specification `section 6.7.2 `_ -opencl_hint_unroll +opencl_unroll_hint ^^^^^^^^^^^^^^^^^^ The implementation of this feature mirrors the unroll hint for C. More details on the syntax can be found in the specification `section 6.11.5 `_ convergent ^^^^^^^^^^ To make sure no invalid optimizations occur for single program multiple data (SPMD) / single instruction multiple thread (SIMT) Clang provides attributes that can be used for special functions that have cross work item semantics. An example is the subgroup operations such as `intel_sub_group_shuffle `_ .. code-block:: c // Define custom my_sub_group_shuffle(data, c) // that makes use of intel_sub_group_shuffle r1 = … if (r0) r1 = computeA(); // Shuffle data from r1 into r3 // of threads id r2. r3 = my_sub_group_shuffle(r1, r2); if (r0) r3 = computeB(); with non-SPMD semantics this is optimized to the following equivalent code: .. code-block:: c r1 = … if (!r0) // Incorrect functionality! The data in r1 // have not been computed by all threads yet. r3 = my_sub_group_shuffle(r1, r2); else { r1 = computeA(); r3 = my_sub_group_shuffle(r1, r2); r3 = computeB(); } Declaring the function ``my_sub_group_shuffle`` with the convergent attribute would prevent this: .. code-block:: c my_sub_group_shuffle() __attribute__((convergent)); Using ``convergent`` guarantees correct execution by keeping CFG equivalence wrt operations marked as ``convergent``. CFG ``G´`` is equivalent to ``G`` wrt node ``Ni`` : ``iff ∀ Nj (i≠j)`` domination and post-domination relations with respect to ``Ni`` remain the same in both ``G`` and ``G´``. noduplicate ^^^^^^^^^^^ ``noduplicate`` is more restrictive with respect to optimizations than ``convergent`` because a convergent function only preserves CFG equivalence. This allows some optimizations to happen as long as the control flow remains unmodified. .. code-block:: c for (int i=0; i<4; i++) my_sub_group_shuffle() can be modified to: .. code-block:: c my_sub_group_shuffle(); my_sub_group_shuffle(); my_sub_group_shuffle(); my_sub_group_shuffle(); while using ``noduplicate`` would disallow this. Also ``noduplicate`` doesn't have the same safe semantics of CFG as ``convergent`` and can cause changes in CFG that modify semantics of the original program. ``noduplicate`` is kept for backwards compatibility only and it considered to be deprecated for future uses. .. _opencl_addrsp: address_space ^^^^^^^^^^^^^ Clang has arbitrary address space support using the ``address_space(N)`` attribute, where ``N`` is an integer number in the range ``0`` to ``16777215`` (``0xffffffu``). An OpenCL implementation provides a list of standard address spaces using keywords: ``private``, ``local``, ``global``, and ``generic``. In the AST and in the IR local, global, or generic will be represented by the address space attribute with the corresponding unique number. Note that private does not have any corresponding attribute added and, therefore, is represented by the absence of an address space number. The specific IDs for an address space do not have to match between the AST and the IR. Typically in the AST address space numbers represent logical segments while in the IR they represent physical segments. Therefore, machines with flat memory segments can map all AST address space numbers to the same physical segment ID or skip address space attribute completely while generating the IR. However, if the address space information is needed by the IR passes e.g. to improve alias analysis, it is recommended to keep it and only lower to reflect physical memory segments in the late machine passes. OpenCL builtins --------------- There are some standard OpenCL functions that are implemented as Clang builtins: - All pipe functions from `section 6.13.16.2/6.13.16.3 `_ of the OpenCL v2.0 kernel language specification. ` - Address space qualifier conversion functions ``to_global``/``to_local``/``to_private`` from `section 6.13.9 `_. - All the ``enqueue_kernel`` functions from `section 6.13.17.1 `_ and enqueue query functions from `section 6.13.17.5 `_. .. _target_features: Target-Specific Features and Limitations ======================================== CPU Architectures Features and Limitations ------------------------------------------ X86 ^^^ The support for X86 (both 32-bit and 64-bit) is considered stable on Darwin (Mac OS X), Linux, FreeBSD, and Dragonfly BSD: it has been tested to correctly compile many large C, C++, Objective-C, and Objective-C++ codebases. On ``x86_64-mingw32``, passing i128(by value) is incompatible with the Microsoft x64 calling convention. You might need to tweak ``WinX86_64ABIInfo::classify()`` in lib/CodeGen/TargetInfo.cpp. For the X86 target, clang supports the `-m16` command line argument which enables 16-bit code output. This is broadly similar to using ``asm(".code16gcc")`` with the GNU toolchain. The generated code and the ABI remains 32-bit but the assembler emits instructions appropriate for a CPU running in 16-bit mode, with address-size and operand-size prefixes to enable 32-bit addressing and operations. ARM ^^^ The support for ARM (specifically ARMv6 and ARMv7) is considered stable on Darwin (iOS): it has been tested to correctly compile many large C, C++, Objective-C, and Objective-C++ codebases. Clang only supports a limited number of ARM architectures. It does not yet fully support ARMv5, for example. PowerPC ^^^^^^^ The support for PowerPC (especially PowerPC64) is considered stable on Linux and FreeBSD: it has been tested to correctly compile many large C and C++ codebases. PowerPC (32bit) is still missing certain features (e.g. PIC code on ELF platforms). Other platforms ^^^^^^^^^^^^^^^ clang currently contains some support for other architectures (e.g. Sparc); however, significant pieces of code generation are still missing, and they haven't undergone significant testing. clang contains limited support for the MSP430 embedded processor, but both the clang support and the LLVM backend support are highly experimental. Other platforms are completely unsupported at the moment. Adding the minimal support needed for parsing and semantic analysis on a new platform is quite easy; see ``lib/Basic/Targets.cpp`` in the clang source tree. This level of support is also sufficient for conversion to LLVM IR for simple programs. Proper support for conversion to LLVM IR requires adding code to ``lib/CodeGen/CGCall.cpp`` at the moment; this is likely to change soon, though. Generating assembly requires a suitable LLVM backend. Operating System Features and Limitations ----------------------------------------- Darwin (Mac OS X) ^^^^^^^^^^^^^^^^^ Thread Sanitizer is not supported. Windows ^^^^^^^ Clang has experimental support for targeting "Cygming" (Cygwin / MinGW) platforms. See also :ref:`Microsoft Extensions `. Cygwin """""" Clang works on Cygwin-1.7. MinGW32 """"""" Clang works on some mingw32 distributions. Clang assumes directories as below; - ``C:/mingw/include`` - ``C:/mingw/lib`` - ``C:/mingw/lib/gcc/mingw32/4.[3-5].0/include/c++`` On MSYS, a few tests might fail. MinGW-w64 """"""""" For 32-bit (i686-w64-mingw32), and 64-bit (x86\_64-w64-mingw32), Clang assumes as below; - ``GCC versions 4.5.0 to 4.5.3, 4.6.0 to 4.6.2, or 4.7.0 (for the C++ header search path)`` - ``some_directory/bin/gcc.exe`` - ``some_directory/bin/clang.exe`` - ``some_directory/bin/clang++.exe`` - ``some_directory/bin/../include/c++/GCC_version`` - ``some_directory/bin/../include/c++/GCC_version/x86_64-w64-mingw32`` - ``some_directory/bin/../include/c++/GCC_version/i686-w64-mingw32`` - ``some_directory/bin/../include/c++/GCC_version/backward`` - ``some_directory/bin/../x86_64-w64-mingw32/include`` - ``some_directory/bin/../i686-w64-mingw32/include`` - ``some_directory/bin/../include`` This directory layout is standard for any toolchain you will find on the official `MinGW-w64 website `_. Clang expects the GCC executable "gcc.exe" compiled for ``i686-w64-mingw32`` (or ``x86_64-w64-mingw32``) to be present on PATH. `Some tests might fail `_ on ``x86_64-w64-mingw32``. .. _clang-cl: clang-cl ======== clang-cl is an alternative command-line interface to Clang, designed for compatibility with the Visual C++ compiler, cl.exe. To enable clang-cl to find system headers, libraries, and the linker when run from the command-line, it should be executed inside a Visual Studio Native Tools Command Prompt or a regular Command Prompt where the environment has been set up using e.g. `vcvars32.bat `_. clang-cl can also be used from inside Visual Studio by using an LLVM Platform Toolset. Command-Line Options -------------------- To be compatible with cl.exe, clang-cl supports most of the same command-line options. Those options can start with either ``/`` or ``-``. It also supports some of Clang's core options, such as the ``-W`` options. Options that are known to clang-cl, but not currently supported, are ignored with a warning. For example: :: clang-cl.exe: warning: argument unused during compilation: '/AI' To suppress warnings about unused arguments, use the ``-Qunused-arguments`` option. Options that are not known to clang-cl will be ignored by default. Use the ``-Werror=unknown-argument`` option in order to treat them as errors. If these options are spelled with a leading ``/``, they will be mistaken for a filename: :: clang-cl.exe: error: no such file or directory: '/foobar' Please `file a bug `_ for any valid cl.exe flags that clang-cl does not understand. Execute ``clang-cl /?`` to see a list of supported options: :: CL.EXE COMPATIBILITY OPTIONS: /? Display available options /arch: Set architecture for code generation /Brepro- Emit an object file which cannot be reproduced over time /Brepro Emit an object file which can be reproduced over time /C Don't discard comments when preprocessing /c Compile only /D Define macro /EH Exception handling model /EP Disable linemarker output and preprocess to stdout /execution-charset: Runtime encoding, supports only UTF-8 /E Preprocess to stdout /fallback Fall back to cl.exe if clang-cl fails to compile /FA Output assembly code file during compilation /Fa Output assembly code to this file during compilation (with /FA) /Fe Set output executable file or directory (ends in / or \) /FI Include file before parsing /Fi Set preprocess output file name (with /P) /Fo Set output object file, or directory (ends in / or \) (with /c) /fp:except- /fp:except /fp:fast /fp:precise /fp:strict /Fp Set pch filename (with /Yc and /Yu) /GA Assume thread-local variables are defined in the executable /Gd Set __cdecl as a default calling convention /GF- Disable string pooling /GR- Disable emission of RTTI data /GR Enable emission of RTTI data /Gr Set __fastcall as a default calling convention /GS- Disable buffer security check /GS Enable buffer security check /Gs Set stack probe size /Gv Set __vectorcall as a default calling convention /Gw- Don't put each data item in its own section /Gw Put each data item in its own section /GX- Enable exception handling /GX Enable exception handling /Gy- Don't put each function in its own section /Gy Put each function in its own section /Gz Set __stdcall as a default calling convention /help Display available options /imsvc Add directory to system include search path, as if part of %INCLUDE% /I Add directory to include search path /J Make char type unsigned /LDd Create debug DLL /LD Create DLL /link Forward options to the linker /MDd Use DLL debug run-time /MD Use DLL run-time /MTd Use static debug run-time /MT Use static run-time /Od Disable optimization /Oi- Disable use of builtin functions /Oi Enable use of builtin functions /Os Optimize for size /Ot Optimize for speed /O Optimization level /o Set output file or directory (ends in / or \) /P Preprocess to file /Qvec- Disable the loop vectorization passes /Qvec Enable the loop vectorization passes /showIncludes Print info about included files to stderr /source-charset: Source encoding, supports only UTF-8 /std: Language standard to compile for /TC Treat all source files as C /Tc Specify a C source file /TP Treat all source files as C++ /Tp Specify a C++ source file /utf-8 Set source and runtime encoding to UTF-8 (default) /U Undefine macro /vd Control vtordisp placement /vmb Use a best-case representation method for member pointers /vmg Use a most-general representation for member pointers /vmm Set the default most-general representation to multiple inheritance /vms Set the default most-general representation to single inheritance /vmv Set the default most-general representation to virtual inheritance /volatile:iso Volatile loads and stores have standard semantics /volatile:ms Volatile loads and stores have acquire and release semantics /W0 Disable all warnings /W1 Enable -Wall /W2 Enable -Wall /W3 Enable -Wall /W4 Enable -Wall and -Wextra /Wall Enable -Wall and -Wextra /WX- Do not treat warnings as errors /WX Treat warnings as errors /w Disable all warnings /Y- Disable precompiled headers, overrides /Yc and /Yu /Yc Generate a pch file for all code up to and including /Yu Load a pch file and use it instead of all code up to and including /Z7 Enable CodeView debug information in object files /Zc:sizedDealloc- Disable C++14 sized global deallocation functions /Zc:sizedDealloc Enable C++14 sized global deallocation functions /Zc:strictStrings Treat string literals as const /Zc:threadSafeInit- Disable thread-safe initialization of static variables /Zc:threadSafeInit Enable thread-safe initialization of static variables /Zc:trigraphs- Disable trigraphs (default) /Zc:trigraphs Enable trigraphs /Zd Emit debug line number tables only /Zi Alias for /Z7. Does not produce PDBs. /Zl Don't mention any default libraries in the object file /Zp Set the default maximum struct packing alignment to 1 /Zp Specify the default maximum struct packing alignment /Zs Syntax-check only OPTIONS: -### Print (but do not run) the commands to run for this compilation --analyze Run the static analyzer -fansi-escape-codes Use ANSI escape codes for diagnostics -fcolor-diagnostics Use colors in diagnostics -fdelayed-template-parsing Parse templated function definitions at the end of the translation unit -fdiagnostics-absolute-paths Print absolute paths in diagnostics -fdiagnostics-parseable-fixits Print fix-its in machine parseable form -flto Enable LTO in 'full' mode -fms-compatibility-version= Dot-separated value representing the Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default)) -fms-compatibility Enable full Microsoft Visual C++ compatibility -fms-extensions Accept some non-standard constructs supported by the Microsoft compiler -fmsc-version= Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default)) -fno-delayed-template-parsing Disable delayed template parsing -fno-sanitize-coverage= Disable specified features of coverage instrumentation for Sanitizers -fno-sanitize-recover= Disable recovery for specified sanitizers -fno-sanitize-trap= Disable trapping for specified sanitizers -fno-standalone-debug Limit debug information produced to reduce size of debug binary -fprofile-instr-generate= Generate instrumented code to collect execution counts into (overridden by LLVM_PROFILE_FILE env var) -fprofile-instr-generate Generate instrumented code to collect execution counts into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var) -fprofile-instr-use= Use instrumentation data for profile-guided optimization -fsanitize-blacklist= Path to blacklist file for sanitizers -fsanitize-coverage= Specify the type of coverage instrumentation for Sanitizers -fsanitize-recover= Enable recovery for specified sanitizers -fsanitize-trap= Enable trapping for specified sanitizers -fsanitize= Turn on runtime checks for various forms of undefined or suspicious behavior. See user manual for available checks -fstandalone-debug Emit full debug info for all types used by the program -gcodeview Generate CodeView debug information -gline-tables-only Emit debug line number tables only -miamcu Use Intel MCU ABI -mllvm Additional arguments to forward to LLVM's option processing -Qunused-arguments Don't emit warning for unused driver arguments -R Enable the specified remark --target= Generate code for the given target -v Show commands to run and use verbose output -W Enable the specified warning -Xclang Pass to the clang compiler The /fallback Option ^^^^^^^^^^^^^^^^^^^^ When clang-cl is run with the ``/fallback`` option, it will first try to compile files itself. For any file that it fails to compile, it will fall back and try to compile the file by invoking cl.exe. This option is intended to be used as a temporary means to build projects where clang-cl cannot successfully compile all the files. clang-cl may fail to compile a file either because it cannot generate code for some C++ feature, or because it cannot parse some Microsoft language extension. Index: vendor/clang/dist/lib/AST/ExprConstant.cpp =================================================================== --- vendor/clang/dist/lib/AST/ExprConstant.cpp (revision 313882) +++ vendor/clang/dist/lib/AST/ExprConstant.cpp (revision 313883) @@ -1,10540 +1,10560 @@ //===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the Expr constant evaluator. // // Constant expression evaluation produces four main results: // // * A success/failure flag indicating whether constant folding was successful. // This is the 'bool' return value used by most of the code in this file. A // 'false' return value indicates that constant folding has failed, and any // appropriate diagnostic has already been produced. // // * An evaluated result, valid only if constant folding has not failed. // // * A flag indicating if evaluation encountered (unevaluated) side-effects. // These arise in cases such as (sideEffect(), 0) and (sideEffect() || 1), // where it is possible to determine the evaluated result regardless. // // * A set of notes indicating why the evaluation was not a constant expression // (under the C++11 / C++1y rules only, at the moment), or, if folding failed // too, why the expression could not be folded. // // If we are checking for a potential constant expression, failure to constant // fold a potential constant sub-expression will be indicated by a 'false' // return value (the expression could not be folded) and no diagnostic (the // expression is not necessarily non-constant). // //===----------------------------------------------------------------------===// #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace clang; using llvm::APSInt; using llvm::APFloat; static bool IsGlobalLValue(APValue::LValueBase B); namespace { struct LValue; struct CallStackFrame; struct EvalInfo; static QualType getType(APValue::LValueBase B) { if (!B) return QualType(); if (const ValueDecl *D = B.dyn_cast()) return D->getType(); const Expr *Base = B.get(); // For a materialized temporary, the type of the temporary we materialized // may not be the type of the expression. if (const MaterializeTemporaryExpr *MTE = dyn_cast(Base)) { SmallVector CommaLHSs; SmallVector Adjustments; const Expr *Temp = MTE->GetTemporaryExpr(); const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // Keep any cv-qualifiers from the reference if we generated a temporary // for it directly. Otherwise use the type after adjustment. if (!Adjustments.empty()) return Inner->getType(); } return Base->getType(); } /// Get an LValue path entry, which is known to not be an array index, as a /// field or base class. static APValue::BaseOrMemberType getAsBaseOrMember(APValue::LValuePathEntry E) { APValue::BaseOrMemberType Value; Value.setFromOpaqueValue(E.BaseOrMember); return Value; } /// Get an LValue path entry, which is known to not be an array index, as a /// field declaration. static const FieldDecl *getAsField(APValue::LValuePathEntry E) { return dyn_cast(getAsBaseOrMember(E).getPointer()); } /// Get an LValue path entry, which is known to not be an array index, as a /// base class declaration. static const CXXRecordDecl *getAsBaseClass(APValue::LValuePathEntry E) { return dyn_cast(getAsBaseOrMember(E).getPointer()); } /// Determine whether this LValue path entry for a base class names a virtual /// base class. static bool isVirtualBaseClass(APValue::LValuePathEntry E) { return getAsBaseOrMember(E).getInt(); } /// Given a CallExpr, try to get the alloc_size attribute. May return null. static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) { const FunctionDecl *Callee = CE->getDirectCallee(); return Callee ? Callee->getAttr() : nullptr; } /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr. /// This will look through a single cast. /// /// Returns null if we couldn't unwrap a function with alloc_size. static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) { if (!E->getType()->isPointerType()) return nullptr; E = E->IgnoreParens(); // If we're doing a variable assignment from e.g. malloc(N), there will // probably be a cast of some kind. Ignore it. if (const auto *Cast = dyn_cast(E)) E = Cast->getSubExpr()->IgnoreParens(); if (const auto *CE = dyn_cast(E)) return getAllocSizeAttr(CE) ? CE : nullptr; return nullptr; } /// Determines whether or not the given Base contains a call to a function /// with the alloc_size attribute. static bool isBaseAnAllocSizeCall(APValue::LValueBase Base) { const auto *E = Base.dyn_cast(); return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E); } /// Determines if an LValue with the given LValueBase will have an unsized /// array in its designator. /// Find the path length and type of the most-derived subobject in the given /// path, and find the size of the containing array, if any. static unsigned findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base, ArrayRef Path, uint64_t &ArraySize, QualType &Type, bool &IsArray) { // This only accepts LValueBases from APValues, and APValues don't support // arrays that lack size info. assert(!isBaseAnAllocSizeCall(Base) && "Unsized arrays shouldn't appear here"); unsigned MostDerivedLength = 0; Type = getType(Base); for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (Type->isArrayType()) { const ConstantArrayType *CAT = cast(Ctx.getAsArrayType(Type)); Type = CAT->getElementType(); ArraySize = CAT->getSize().getZExtValue(); MostDerivedLength = I + 1; IsArray = true; } else if (Type->isAnyComplexType()) { const ComplexType *CT = Type->castAs(); Type = CT->getElementType(); ArraySize = 2; MostDerivedLength = I + 1; IsArray = true; } else if (const FieldDecl *FD = getAsField(Path[I])) { Type = FD->getType(); ArraySize = 0; MostDerivedLength = I + 1; IsArray = false; } else { // Path[I] describes a base class. ArraySize = 0; IsArray = false; } } return MostDerivedLength; } // The order of this enum is important for diagnostics. enum CheckSubobjectKind { CSK_Base, CSK_Derived, CSK_Field, CSK_ArrayToPointer, CSK_ArrayIndex, CSK_This, CSK_Real, CSK_Imag }; /// A path from a glvalue to a subobject of that glvalue. struct SubobjectDesignator { /// True if the subobject was named in a manner not supported by C++11. Such /// lvalues can still be folded, but they are not core constant expressions /// and we cannot perform lvalue-to-rvalue conversions on them. unsigned Invalid : 1; /// Is this a pointer one past the end of an object? unsigned IsOnePastTheEnd : 1; /// Indicator of whether the first entry is an unsized array. unsigned FirstEntryIsAnUnsizedArray : 1; /// Indicator of whether the most-derived object is an array element. unsigned MostDerivedIsArrayElement : 1; /// The length of the path to the most-derived object of which this is a /// subobject. unsigned MostDerivedPathLength : 28; /// The size of the array of which the most-derived object is an element. /// This will always be 0 if the most-derived object is not an array /// element. 0 is not an indicator of whether or not the most-derived object /// is an array, however, because 0-length arrays are allowed. /// /// If the current array is an unsized array, the value of this is /// undefined. uint64_t MostDerivedArraySize; /// The type of the most derived object referred to by this address. QualType MostDerivedType; typedef APValue::LValuePathEntry PathEntry; /// The entries on the path from the glvalue to the designated subobject. SmallVector Entries; SubobjectDesignator() : Invalid(true) {} explicit SubobjectDesignator(QualType T) : Invalid(false), IsOnePastTheEnd(false), FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), MostDerivedPathLength(0), MostDerivedArraySize(0), MostDerivedType(T) {} SubobjectDesignator(ASTContext &Ctx, const APValue &V) : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false), FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false), MostDerivedPathLength(0), MostDerivedArraySize(0) { assert(V.isLValue() && "Non-LValue used to make an LValue designator?"); if (!Invalid) { IsOnePastTheEnd = V.isLValueOnePastTheEnd(); ArrayRef VEntries = V.getLValuePath(); Entries.insert(Entries.end(), VEntries.begin(), VEntries.end()); if (V.getLValueBase()) { bool IsArray = false; MostDerivedPathLength = findMostDerivedSubobject( Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize, MostDerivedType, IsArray); MostDerivedIsArrayElement = IsArray; } } } void setInvalid() { Invalid = true; Entries.clear(); } /// Determine whether the most derived subobject is an array without a /// known bound. bool isMostDerivedAnUnsizedArray() const { assert(!Invalid && "Calling this makes no sense on invalid designators"); return Entries.size() == 1 && FirstEntryIsAnUnsizedArray; } /// Determine what the most derived array's size is. Results in an assertion /// failure if the most derived array lacks a size. uint64_t getMostDerivedArraySize() const { assert(!isMostDerivedAnUnsizedArray() && "Unsized array has no size"); return MostDerivedArraySize; } /// Determine whether this is a one-past-the-end pointer. bool isOnePastTheEnd() const { assert(!Invalid); if (IsOnePastTheEnd) return true; if (!isMostDerivedAnUnsizedArray() && MostDerivedIsArrayElement && Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize) return true; return false; } /// Check that this refers to a valid subobject. bool isValidSubobject() const { if (Invalid) return false; return !isOnePastTheEnd(); } /// Check that this refers to a valid subobject, and if not, produce a /// relevant diagnostic and set the designator as invalid. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK); /// Update this designator to refer to the first element within this array. void addArrayUnchecked(const ConstantArrayType *CAT) { PathEntry Entry; Entry.ArrayIndex = 0; Entries.push_back(Entry); // This is a most-derived object. MostDerivedType = CAT->getElementType(); MostDerivedIsArrayElement = true; MostDerivedArraySize = CAT->getSize().getZExtValue(); MostDerivedPathLength = Entries.size(); } /// Update this designator to refer to the first element within the array of /// elements of type T. This is an array of unknown size. void addUnsizedArrayUnchecked(QualType ElemTy) { PathEntry Entry; Entry.ArrayIndex = 0; Entries.push_back(Entry); MostDerivedType = ElemTy; MostDerivedIsArrayElement = true; // The value in MostDerivedArraySize is undefined in this case. So, set it // to an arbitrary value that's likely to loudly break things if it's // used. MostDerivedArraySize = std::numeric_limits::max() / 2; MostDerivedPathLength = Entries.size(); } /// Update this designator to refer to the given base or member of this /// object. void addDeclUnchecked(const Decl *D, bool Virtual = false) { PathEntry Entry; APValue::BaseOrMemberType Value(D, Virtual); Entry.BaseOrMember = Value.getOpaqueValue(); Entries.push_back(Entry); // If this isn't a base class, it's a new most-derived object. if (const FieldDecl *FD = dyn_cast(D)) { MostDerivedType = FD->getType(); MostDerivedIsArrayElement = false; MostDerivedArraySize = 0; MostDerivedPathLength = Entries.size(); } } /// Update this designator to refer to the given complex component. void addComplexUnchecked(QualType EltTy, bool Imag) { PathEntry Entry; Entry.ArrayIndex = Imag; Entries.push_back(Entry); // This is technically a most-derived object, though in practice this // is unlikely to matter. MostDerivedType = EltTy; MostDerivedIsArrayElement = true; MostDerivedArraySize = 2; MostDerivedPathLength = Entries.size(); } void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N); /// Add N to the address of this subobject. void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { if (Invalid) return; if (isMostDerivedAnUnsizedArray()) { // Can't verify -- trust that the user is doing the right thing (or if // not, trust that the caller will catch the bad behavior). Entries.back().ArrayIndex += N; return; } if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) { Entries.back().ArrayIndex += N; if (Entries.back().ArrayIndex > getMostDerivedArraySize()) { diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex); setInvalid(); } return; } // [expr.add]p4: For the purposes of these operators, a pointer to a // nonarray object behaves the same as a pointer to the first element of // an array of length one with the type of the object as its element type. if (IsOnePastTheEnd && N == (uint64_t)-1) IsOnePastTheEnd = false; else if (!IsOnePastTheEnd && N == 1) IsOnePastTheEnd = true; else if (N != 0) { diagnosePointerArithmetic(Info, E, uint64_t(IsOnePastTheEnd) + N); setInvalid(); } } }; /// A stack frame in the constexpr call stack. struct CallStackFrame { EvalInfo &Info; /// Parent - The caller of this stack frame. CallStackFrame *Caller; /// Callee - The function which was called. const FunctionDecl *Callee; /// This - The binding for the this pointer in this call, if any. const LValue *This; /// Arguments - Parameter bindings for this function call, indexed by /// parameters' function scope indices. APValue *Arguments; // Note that we intentionally use std::map here so that references to // values are stable. typedef std::map MapTy; typedef MapTy::const_iterator temp_iterator; /// Temporaries - Temporary lvalues materialized within this stack frame. MapTy Temporaries; /// CallLoc - The location of the call expression for this call. SourceLocation CallLoc; /// Index - The call index of this call. unsigned Index; CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments); ~CallStackFrame(); APValue *getTemporary(const void *Key) { MapTy::iterator I = Temporaries.find(Key); return I == Temporaries.end() ? nullptr : &I->second; } APValue &createTemporary(const void *Key, bool IsLifetimeExtended); }; /// Temporarily override 'this'. class ThisOverrideRAII { public: ThisOverrideRAII(CallStackFrame &Frame, const LValue *NewThis, bool Enable) : Frame(Frame), OldThis(Frame.This) { if (Enable) Frame.This = NewThis; } ~ThisOverrideRAII() { Frame.This = OldThis; } private: CallStackFrame &Frame; const LValue *OldThis; }; /// A partial diagnostic which we might know in advance that we are not going /// to emit. class OptionalDiagnostic { PartialDiagnostic *Diag; public: explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) : Diag(Diag) {} template OptionalDiagnostic &operator<<(const T &v) { if (Diag) *Diag << v; return *this; } OptionalDiagnostic &operator<<(const APSInt &I) { if (Diag) { SmallVector Buffer; I.toString(Buffer); *Diag << StringRef(Buffer.data(), Buffer.size()); } return *this; } OptionalDiagnostic &operator<<(const APFloat &F) { if (Diag) { // FIXME: Force the precision of the source value down so we don't // print digits which are usually useless (we don't really care here if // we truncate a digit by accident in edge cases). Ideally, // APFloat::toString would automatically print the shortest // representation which rounds to the correct value, but it's a bit // tricky to implement. unsigned precision = llvm::APFloat::semanticsPrecision(F.getSemantics()); precision = (precision * 59 + 195) / 196; SmallVector Buffer; F.toString(Buffer, precision); *Diag << StringRef(Buffer.data(), Buffer.size()); } return *this; } }; /// A cleanup, and a flag indicating whether it is lifetime-extended. class Cleanup { llvm::PointerIntPair Value; public: Cleanup(APValue *Val, bool IsLifetimeExtended) : Value(Val, IsLifetimeExtended) {} bool isLifetimeExtended() const { return Value.getInt(); } void endLifetime() { *Value.getPointer() = APValue(); } }; /// EvalInfo - This is a private struct used by the evaluator to capture /// information about a subexpression as it is folded. It retains information /// about the AST context, but also maintains information about the folded /// expression. /// /// If an expression could be evaluated, it is still possible it is not a C /// "integer constant expression" or constant expression. If not, this struct /// captures information about how and why not. /// /// One bit of information passed *into* the request for constant folding /// indicates whether the subexpression is "evaluated" or not according to C /// rules. For example, the RHS of (0 && foo()) is not evaluated. We can /// evaluate the expression regardless of what the RHS is, but C only allows /// certain things in certain situations. struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EvalInfo { ASTContext &Ctx; /// EvalStatus - Contains information about the evaluation. Expr::EvalStatus &EvalStatus; /// CurrentCall - The top of the constexpr call stack. CallStackFrame *CurrentCall; /// CallStackDepth - The number of calls in the call stack right now. unsigned CallStackDepth; /// NextCallIndex - The next call index to assign. unsigned NextCallIndex; /// StepsLeft - The remaining number of evaluation steps we're permitted /// to perform. This is essentially a limit for the number of statements /// we will evaluate. unsigned StepsLeft; /// BottomFrame - The frame in which evaluation started. This must be /// initialized after CurrentCall and CallStackDepth. CallStackFrame BottomFrame; /// A stack of values whose lifetimes end at the end of some surrounding /// evaluation frame. llvm::SmallVector CleanupStack; /// EvaluatingDecl - This is the declaration whose initializer is being /// evaluated, if any. APValue::LValueBase EvaluatingDecl; /// EvaluatingDeclValue - This is the value being constructed for the /// declaration whose initializer is being evaluated, if any. APValue *EvaluatingDeclValue; /// The current array initialization index, if we're performing array /// initialization. uint64_t ArrayInitIndex = -1; /// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further /// notes attached to it will also be stored, otherwise they will not be. bool HasActiveDiagnostic; /// \brief Have we emitted a diagnostic explaining why we couldn't constant /// fold (not just why it's not strictly a constant expression)? bool HasFoldFailureDiagnostic; /// \brief Whether or not we're currently speculatively evaluating. bool IsSpeculativelyEvaluating; enum EvaluationMode { /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. EM_ConstantExpression, /// Evaluate as a potential constant expression. Keep going if we hit a /// construct that we can't evaluate yet (because we don't yet know the /// value of something) but stop if we hit something that could never be /// a constant expression. EM_PotentialConstantExpression, /// Fold the expression to a constant. Stop if we hit a side-effect that /// we can't model. EM_ConstantFold, /// Evaluate the expression looking for integer overflow and similar /// issues. Don't worry about side-effects, and try to visit all /// subexpressions. EM_EvaluateForOverflow, /// Evaluate in any way we know how. Don't worry about side-effects that /// can't be modeled. EM_IgnoreSideEffects, /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. Some expressions can be retried in the /// optimizer if we don't constant fold them here, but in an unevaluated /// context we try to fold them immediately since the optimizer never /// gets a chance to look at it. EM_ConstantExpressionUnevaluated, /// Evaluate as a potential constant expression. Keep going if we hit a /// construct that we can't evaluate yet (because we don't yet know the /// value of something) but stop if we hit something that could never be /// a constant expression. Some expressions can be retried in the /// optimizer if we don't constant fold them here, but in an unevaluated /// context we try to fold them immediately since the optimizer never /// gets a chance to look at it. EM_PotentialConstantExpressionUnevaluated, - /// Evaluate as a constant expression. Continue evaluating if either: - /// - We find a MemberExpr with a base that can't be evaluated. - /// - We find a variable initialized with a call to a function that has - /// the alloc_size attribute on it. + /// Evaluate as a constant expression. In certain scenarios, if: + /// - we find a MemberExpr with a base that can't be evaluated, or + /// - we find a variable initialized with a call to a function that has + /// the alloc_size attribute on it + /// then we may consider evaluation to have succeeded. + /// /// In either case, the LValue returned shall have an invalid base; in the /// former, the base will be the invalid MemberExpr, in the latter, the /// base will be either the alloc_size CallExpr or a CastExpr wrapping /// said CallExpr. EM_OffsetFold, } EvalMode; /// Are we checking whether the expression is a potential constant /// expression? bool checkingPotentialConstantExpression() const { return EvalMode == EM_PotentialConstantExpression || EvalMode == EM_PotentialConstantExpressionUnevaluated; } /// Are we checking an expression for overflow? // FIXME: We should check for any kind of undefined or suspicious behavior // in such constructs, not just overflow. bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; } EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode) : Ctx(const_cast(C)), EvalStatus(S), CurrentCall(nullptr), CallStackDepth(0), NextCallIndex(1), StepsLeft(getLangOpts().ConstexprStepLimit), BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr), EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; EvaluatingDeclValue = &Value; } const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); } bool CheckCallLimit(SourceLocation Loc) { // Don't perform any constexpr calls (other than the call we're checking) // when checking a potential constant expression. if (checkingPotentialConstantExpression() && CallStackDepth > 1) return false; if (NextCallIndex == 0) { // NextCallIndex has wrapped around. FFDiag(Loc, diag::note_constexpr_call_limit_exceeded); return false; } if (CallStackDepth <= getLangOpts().ConstexprCallDepth) return true; FFDiag(Loc, diag::note_constexpr_depth_limit_exceeded) << getLangOpts().ConstexprCallDepth; return false; } CallStackFrame *getCallFrame(unsigned CallIndex) { assert(CallIndex && "no call index in getCallFrame"); // We will eventually hit BottomFrame, which has Index 1, so Frame can't // be null in this loop. CallStackFrame *Frame = CurrentCall; while (Frame->Index > CallIndex) Frame = Frame->Caller; return (Frame->Index == CallIndex) ? Frame : nullptr; } bool nextStep(const Stmt *S) { if (!StepsLeft) { FFDiag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded); return false; } --StepsLeft; return true; } private: /// Add a diagnostic to the diagnostics list. PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId) { PartialDiagnostic PD(DiagId, Ctx.getDiagAllocator()); EvalStatus.Diag->push_back(std::make_pair(Loc, PD)); return EvalStatus.Diag->back().second; } /// Add notes containing a call stack to the current point of evaluation. void addCallStack(unsigned Limit); private: OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId, unsigned ExtraNotes, bool IsCCEDiag) { if (EvalStatus.Diag) { // If we have a prior diagnostic, it will be noting that the expression // isn't a constant expression. This diagnostic is more important, // unless we require this evaluation to produce a constant expression. // // FIXME: We might want to show both diagnostics to the user in // EM_ConstantFold mode. if (!EvalStatus.Diag->empty()) { switch (EvalMode) { case EM_ConstantFold: case EM_IgnoreSideEffects: case EM_EvaluateForOverflow: if (!HasFoldFailureDiagnostic) break; // We've already failed to fold something. Keep that diagnostic. case EM_ConstantExpression: case EM_PotentialConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_PotentialConstantExpressionUnevaluated: case EM_OffsetFold: HasActiveDiagnostic = false; return OptionalDiagnostic(); } } unsigned CallStackNotes = CallStackDepth - 1; unsigned Limit = Ctx.getDiagnostics().getConstexprBacktraceLimit(); if (Limit) CallStackNotes = std::min(CallStackNotes, Limit + 1); if (checkingPotentialConstantExpression()) CallStackNotes = 0; HasActiveDiagnostic = true; HasFoldFailureDiagnostic = !IsCCEDiag; EvalStatus.Diag->clear(); EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes); addDiag(Loc, DiagId); if (!checkingPotentialConstantExpression()) addCallStack(Limit); return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second); } HasActiveDiagnostic = false; return OptionalDiagnostic(); } public: // Diagnose that the evaluation could not be folded (FF => FoldFailure) OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { return Diag(Loc, DiagId, ExtraNotes, false); } OptionalDiagnostic FFDiag(const Expr *E, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { if (EvalStatus.Diag) return Diag(E->getExprLoc(), DiagId, ExtraNotes, /*IsCCEDiag*/false); HasActiveDiagnostic = false; return OptionalDiagnostic(); } /// Diagnose that the evaluation does not produce a C++11 core constant /// expression. /// /// FIXME: Stop evaluating if we're in EM_ConstantExpression or /// EM_PotentialConstantExpression mode and we produce one of these. OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { // Don't override a previous diagnostic. Don't bother collecting // diagnostics if we're evaluating for overflow. if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) { HasActiveDiagnostic = false; return OptionalDiagnostic(); } return Diag(Loc, DiagId, ExtraNotes, true); } OptionalDiagnostic CCEDiag(const Expr *E, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes); } /// Add a note to a prior diagnostic. OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId) { if (!HasActiveDiagnostic) return OptionalDiagnostic(); return OptionalDiagnostic(&addDiag(Loc, DiagId)); } /// Add a stack of notes to a prior diagnostic. void addNotes(ArrayRef Diags) { if (HasActiveDiagnostic) { EvalStatus.Diag->insert(EvalStatus.Diag->end(), Diags.begin(), Diags.end()); } } /// Should we continue evaluation after encountering a side-effect that we /// couldn't model? bool keepEvaluatingAfterSideEffect() { switch (EvalMode) { case EM_PotentialConstantExpression: case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: return true; case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); } /// Note that we have had a side-effect, and determine whether we should /// keep evaluating. bool noteSideEffect() { EvalStatus.HasSideEffects = true; return keepEvaluatingAfterSideEffect(); } /// Should we continue evaluation after encountering undefined behavior? bool keepEvaluatingAfterUndefinedBehavior() { switch (EvalMode) { case EM_EvaluateForOverflow: case EM_IgnoreSideEffects: case EM_ConstantFold: case EM_OffsetFold: return true; case EM_PotentialConstantExpression: case EM_PotentialConstantExpressionUnevaluated: case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: return false; } llvm_unreachable("Missed EvalMode case"); } /// Note that we hit something that was technically undefined behavior, but /// that we can evaluate past it (such as signed overflow or floating-point /// division by zero.) bool noteUndefinedBehavior() { EvalStatus.HasUndefinedBehavior = true; return keepEvaluatingAfterUndefinedBehavior(); } /// Should we continue evaluation as much as possible after encountering a /// construct which can't be reduced to a value? bool keepEvaluatingAfterFailure() { if (!StepsLeft) return false; switch (EvalMode) { case EM_PotentialConstantExpression: case EM_PotentialConstantExpressionUnevaluated: case EM_EvaluateForOverflow: return true; case EM_ConstantExpression: case EM_ConstantExpressionUnevaluated: case EM_ConstantFold: case EM_IgnoreSideEffects: case EM_OffsetFold: return false; } llvm_unreachable("Missed EvalMode case"); } /// Notes that we failed to evaluate an expression that other expressions /// directly depend on, and determine if we should keep evaluating. This /// should only be called if we actually intend to keep evaluating. /// /// Call noteSideEffect() instead if we may be able to ignore the value that /// we failed to evaluate, e.g. if we failed to evaluate Foo() in: /// /// (Foo(), 1) // use noteSideEffect /// (Foo() || true) // use noteSideEffect /// Foo() + 1 // use noteFailure LLVM_NODISCARD bool noteFailure() { // Failure when evaluating some expression often means there is some // subexpression whose evaluation was skipped. Therefore, (because we // don't track whether we skipped an expression when unwinding after an // evaluation failure) every evaluation failure that bubbles up from a // subexpression implies that a side-effect has potentially happened. We // skip setting the HasSideEffects flag to true until we decide to // continue evaluating after that point, which happens here. bool KeepGoing = keepEvaluatingAfterFailure(); EvalStatus.HasSideEffects |= KeepGoing; return KeepGoing; } - bool allowInvalidBaseExpr() const { - return EvalMode == EM_OffsetFold; - } - class ArrayInitLoopIndex { EvalInfo &Info; uint64_t OuterIndex; public: ArrayInitLoopIndex(EvalInfo &Info) : Info(Info), OuterIndex(Info.ArrayInitIndex) { Info.ArrayInitIndex = 0; } ~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; } operator uint64_t&() { return Info.ArrayInitIndex; } }; }; /// Object used to treat all foldable expressions as constant expressions. struct FoldConstant { EvalInfo &Info; bool Enabled; bool HadNoPriorDiags; EvalInfo::EvaluationMode OldMode; explicit FoldConstant(EvalInfo &Info, bool Enabled) : Info(Info), Enabled(Enabled), HadNoPriorDiags(Info.EvalStatus.Diag && Info.EvalStatus.Diag->empty() && !Info.EvalStatus.HasSideEffects), OldMode(Info.EvalMode) { if (Enabled && (Info.EvalMode == EvalInfo::EM_ConstantExpression || Info.EvalMode == EvalInfo::EM_ConstantExpressionUnevaluated)) Info.EvalMode = EvalInfo::EM_ConstantFold; } void keepDiagnostics() { Enabled = false; } ~FoldConstant() { if (Enabled && HadNoPriorDiags && !Info.EvalStatus.Diag->empty() && !Info.EvalStatus.HasSideEffects) Info.EvalStatus.Diag->clear(); Info.EvalMode = OldMode; } }; /// RAII object used to treat the current evaluation as the correct pointer /// offset fold for the current EvalMode struct FoldOffsetRAII { EvalInfo &Info; EvalInfo::EvaluationMode OldMode; explicit FoldOffsetRAII(EvalInfo &Info) : Info(Info), OldMode(Info.EvalMode) { if (!Info.checkingPotentialConstantExpression()) Info.EvalMode = EvalInfo::EM_OffsetFold; } ~FoldOffsetRAII() { Info.EvalMode = OldMode; } }; /// RAII object used to optionally suppress diagnostics and side-effects from /// a speculative evaluation. class SpeculativeEvaluationRAII { /// Pair of EvalInfo, and a bit that stores whether or not we were /// speculatively evaluating when we created this RAII. llvm::PointerIntPair InfoAndOldSpecEval; Expr::EvalStatus Old; void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) { InfoAndOldSpecEval = Other.InfoAndOldSpecEval; Old = Other.Old; Other.InfoAndOldSpecEval.setPointer(nullptr); } void maybeRestoreState() { EvalInfo *Info = InfoAndOldSpecEval.getPointer(); if (!Info) return; Info->EvalStatus = Old; Info->IsSpeculativelyEvaluating = InfoAndOldSpecEval.getInt(); } public: SpeculativeEvaluationRAII() = default; SpeculativeEvaluationRAII( EvalInfo &Info, SmallVectorImpl *NewDiag = nullptr) : InfoAndOldSpecEval(&Info, Info.IsSpeculativelyEvaluating), Old(Info.EvalStatus) { Info.EvalStatus.Diag = NewDiag; Info.IsSpeculativelyEvaluating = true; } SpeculativeEvaluationRAII(const SpeculativeEvaluationRAII &Other) = delete; SpeculativeEvaluationRAII(SpeculativeEvaluationRAII &&Other) { moveFromAndCancel(std::move(Other)); } SpeculativeEvaluationRAII &operator=(SpeculativeEvaluationRAII &&Other) { maybeRestoreState(); moveFromAndCancel(std::move(Other)); return *this; } ~SpeculativeEvaluationRAII() { maybeRestoreState(); } }; /// RAII object wrapping a full-expression or block scope, and handling /// the ending of the lifetime of temporaries created within it. template class ScopeRAII { EvalInfo &Info; unsigned OldStackSize; public: ScopeRAII(EvalInfo &Info) : Info(Info), OldStackSize(Info.CleanupStack.size()) {} ~ScopeRAII() { // Body moved to a static method to encourage the compiler to inline away // instances of this class. cleanup(Info, OldStackSize); } private: static void cleanup(EvalInfo &Info, unsigned OldStackSize) { unsigned NewEnd = OldStackSize; for (unsigned I = OldStackSize, N = Info.CleanupStack.size(); I != N; ++I) { if (IsFullExpression && Info.CleanupStack[I].isLifetimeExtended()) { // Full-expression cleanup of a lifetime-extended temporary: nothing // to do, just move this cleanup to the right place in the stack. std::swap(Info.CleanupStack[I], Info.CleanupStack[NewEnd]); ++NewEnd; } else { // End the lifetime of the object. Info.CleanupStack[I].endLifetime(); } } Info.CleanupStack.erase(Info.CleanupStack.begin() + NewEnd, Info.CleanupStack.end()); } }; typedef ScopeRAII BlockScopeRAII; typedef ScopeRAII FullExpressionRAII; } bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { if (Invalid) return false; if (isOnePastTheEnd()) { Info.CCEDiag(E, diag::note_constexpr_past_end_subobject) << CSK; setInvalid(); return false; } return true; } void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N) { // If we're complaining, we must be able to statically determine the size of // the most derived array. if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement) Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast(N) << /*array*/ 0 << static_cast(getMostDerivedArraySize()); else Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast(N) << /*non-array*/ 1; setInvalid(); } CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, APValue *Arguments) : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This), Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) { Info.CurrentCall = this; ++Info.CallStackDepth; } CallStackFrame::~CallStackFrame() { assert(Info.CurrentCall == this && "calls retired out of order"); --Info.CallStackDepth; Info.CurrentCall = Caller; } APValue &CallStackFrame::createTemporary(const void *Key, bool IsLifetimeExtended) { APValue &Result = Temporaries[Key]; assert(Result.isUninit() && "temporary created multiple times"); Info.CleanupStack.push_back(Cleanup(&Result, IsLifetimeExtended)); return Result; } static void describeCall(CallStackFrame *Frame, raw_ostream &Out); void EvalInfo::addCallStack(unsigned Limit) { // Determine which calls to skip, if any. unsigned ActiveCalls = CallStackDepth - 1; unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart; if (Limit && Limit < ActiveCalls) { SkipStart = Limit / 2 + Limit % 2; SkipEnd = ActiveCalls - Limit / 2; } // Walk the call stack and add the diagnostics. unsigned CallIdx = 0; for (CallStackFrame *Frame = CurrentCall; Frame != &BottomFrame; Frame = Frame->Caller, ++CallIdx) { // Skip this call? if (CallIdx >= SkipStart && CallIdx < SkipEnd) { if (CallIdx == SkipStart) { // Note that we're skipping calls. addDiag(Frame->CallLoc, diag::note_constexpr_calls_suppressed) << unsigned(ActiveCalls - Limit); } continue; } // Use a different note for an inheriting constructor, because from the // user's perspective it's not really a function at all. if (auto *CD = dyn_cast_or_null(Frame->Callee)) { if (CD->isInheritingConstructor()) { addDiag(Frame->CallLoc, diag::note_constexpr_inherited_ctor_call_here) << CD->getParent(); continue; } } SmallVector Buffer; llvm::raw_svector_ostream Out(Buffer); describeCall(Frame, Out); addDiag(Frame->CallLoc, diag::note_constexpr_call_here) << Out.str(); } } namespace { struct ComplexValue { private: bool IsInt; public: APSInt IntReal, IntImag; APFloat FloatReal, FloatImag; ComplexValue() : FloatReal(APFloat::Bogus()), FloatImag(APFloat::Bogus()) {} void makeComplexFloat() { IsInt = false; } bool isComplexFloat() const { return !IsInt; } APFloat &getComplexFloatReal() { return FloatReal; } APFloat &getComplexFloatImag() { return FloatImag; } void makeComplexInt() { IsInt = true; } bool isComplexInt() const { return IsInt; } APSInt &getComplexIntReal() { return IntReal; } APSInt &getComplexIntImag() { return IntImag; } void moveInto(APValue &v) const { if (isComplexFloat()) v = APValue(FloatReal, FloatImag); else v = APValue(IntReal, IntImag); } void setFrom(const APValue &v) { assert(v.isComplexFloat() || v.isComplexInt()); if (v.isComplexFloat()) { makeComplexFloat(); FloatReal = v.getComplexFloatReal(); FloatImag = v.getComplexFloatImag(); } else { makeComplexInt(); IntReal = v.getComplexIntReal(); IntImag = v.getComplexIntImag(); } } }; struct LValue { APValue::LValueBase Base; CharUnits Offset; unsigned InvalidBase : 1; unsigned CallIndex : 31; SubobjectDesignator Designator; bool IsNullPtr; const APValue::LValueBase getLValueBase() const { return Base; } CharUnits &getLValueOffset() { return Offset; } const CharUnits &getLValueOffset() const { return Offset; } unsigned getLValueCallIndex() const { return CallIndex; } SubobjectDesignator &getLValueDesignator() { return Designator; } const SubobjectDesignator &getLValueDesignator() const { return Designator;} bool isNullPointer() const { return IsNullPtr;} void moveInto(APValue &V) const { if (Designator.Invalid) V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex, IsNullPtr); else { assert(!InvalidBase && "APValues can't handle invalid LValue bases"); assert(!Designator.FirstEntryIsAnUnsizedArray && "Unsized array with a valid base?"); V = APValue(Base, Offset, Designator.Entries, Designator.IsOnePastTheEnd, CallIndex, IsNullPtr); } } void setFrom(ASTContext &Ctx, const APValue &V) { assert(V.isLValue() && "Setting LValue from a non-LValue?"); Base = V.getLValueBase(); Offset = V.getLValueOffset(); InvalidBase = false; CallIndex = V.getLValueCallIndex(); Designator = SubobjectDesignator(Ctx, V); IsNullPtr = V.isNullPointer(); } void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false, bool IsNullPtr_ = false, uint64_t Offset_ = 0) { #ifndef NDEBUG // We only allow a few types of invalid bases. Enforce that here. if (BInvalid) { const auto *E = B.get(); assert((isa(E) || tryUnwrapAllocSizeCall(E)) && "Unexpected type of invalid base"); } #endif Base = B; Offset = CharUnits::fromQuantity(Offset_); InvalidBase = BInvalid; CallIndex = I; Designator = SubobjectDesignator(getType(B)); IsNullPtr = IsNullPtr_; } void setInvalid(APValue::LValueBase B, unsigned I = 0) { set(B, I, true); } // Check that this LValue is not based on a null pointer. If it is, produce // a diagnostic and mark the designator as invalid. bool checkNullPointer(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { if (Designator.Invalid) return false; if (IsNullPtr) { Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; Designator.setInvalid(); return false; } return true; } // Check this LValue refers to an object. If not, set the designator to be // invalid and emit a diagnostic. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) && Designator.checkSubobject(Info, E, CSK); } void addDecl(EvalInfo &Info, const Expr *E, const Decl *D, bool Virtual = false) { if (checkSubobject(Info, E, isa(D) ? CSK_Field : CSK_Base)) Designator.addDeclUnchecked(D, Virtual); } void addUnsizedArray(EvalInfo &Info, QualType ElemTy) { assert(Designator.Entries.empty() && getType(Base)->isPointerType()); assert(isBaseAnAllocSizeCall(Base) && "Only alloc_size bases can have unsized arrays"); Designator.FirstEntryIsAnUnsizedArray = true; Designator.addUnsizedArrayUnchecked(ElemTy); } void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { if (checkSubobject(Info, E, CSK_ArrayToPointer)) Designator.addArrayUnchecked(CAT); } void addComplex(EvalInfo &Info, const Expr *E, QualType EltTy, bool Imag) { if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) Designator.addComplexUnchecked(EltTy, Imag); } void clearIsNullPointer() { IsNullPtr = false; } void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, uint64_t Index, CharUnits ElementSize) { // Compute the new offset in the appropriate width. Offset += Index * ElementSize; if (Index && checkNullPointer(Info, E, CSK_ArrayIndex)) Designator.adjustIndex(Info, E, Index); if (Index) clearIsNullPointer(); } void adjustOffset(CharUnits N) { Offset += N; if (N.getQuantity()) clearIsNullPointer(); } }; struct MemberPtr { MemberPtr() {} explicit MemberPtr(const ValueDecl *Decl) : DeclAndIsDerivedMember(Decl, false), Path() {} /// The member or (direct or indirect) field referred to by this member /// pointer, or 0 if this is a null member pointer. const ValueDecl *getDecl() const { return DeclAndIsDerivedMember.getPointer(); } /// Is this actually a member of some type derived from the relevant class? bool isDerivedMember() const { return DeclAndIsDerivedMember.getInt(); } /// Get the class which the declaration actually lives in. const CXXRecordDecl *getContainingRecord() const { return cast( DeclAndIsDerivedMember.getPointer()->getDeclContext()); } void moveInto(APValue &V) const { V = APValue(getDecl(), isDerivedMember(), Path); } void setFrom(const APValue &V) { assert(V.isMemberPointer()); DeclAndIsDerivedMember.setPointer(V.getMemberPointerDecl()); DeclAndIsDerivedMember.setInt(V.isMemberPointerToDerivedMember()); Path.clear(); ArrayRef P = V.getMemberPointerPath(); Path.insert(Path.end(), P.begin(), P.end()); } /// DeclAndIsDerivedMember - The member declaration, and a flag indicating /// whether the member is a member of some class derived from the class type /// of the member pointer. llvm::PointerIntPair DeclAndIsDerivedMember; /// Path - The path of base/derived classes from the member declaration's /// class (exclusive) to the class type of the member pointer (inclusive). SmallVector Path; /// Perform a cast towards the class of the Decl (either up or down the /// hierarchy). bool castBack(const CXXRecordDecl *Class) { assert(!Path.empty()); const CXXRecordDecl *Expected; if (Path.size() >= 2) Expected = Path[Path.size() - 2]; else Expected = getContainingRecord(); if (Expected->getCanonicalDecl() != Class->getCanonicalDecl()) { // C++11 [expr.static.cast]p12: In a conversion from (D::*) to (B::*), // if B does not contain the original member and is not a base or // derived class of the class containing the original member, the result // of the cast is undefined. // C++11 [conv.mem]p2 does not cover this case for a cast from (B::*) to // (D::*). We consider that to be a language defect. return false; } Path.pop_back(); return true; } /// Perform a base-to-derived member pointer cast. bool castToDerived(const CXXRecordDecl *Derived) { if (!getDecl()) return true; if (!isDerivedMember()) { Path.push_back(Derived); return true; } if (!castBack(Derived)) return false; if (Path.empty()) DeclAndIsDerivedMember.setInt(false); return true; } /// Perform a derived-to-base member pointer cast. bool castToBase(const CXXRecordDecl *Base) { if (!getDecl()) return true; if (Path.empty()) DeclAndIsDerivedMember.setInt(true); if (isDerivedMember()) { Path.push_back(Base); return true; } return castBack(Base); } }; /// Compare two member pointers, which are assumed to be of the same type. static bool operator==(const MemberPtr &LHS, const MemberPtr &RHS) { if (!LHS.getDecl() || !RHS.getDecl()) return !LHS.getDecl() && !RHS.getDecl(); if (LHS.getDecl()->getCanonicalDecl() != RHS.getDecl()->getCanonicalDecl()) return false; return LHS.Path == RHS.Path; } } static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E); static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes = false); -static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); -static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); +static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, + bool InvalidBaseOK = false); +static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info, + bool InvalidBaseOK = false); static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, EvalInfo &Info); static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info); static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info); static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info); static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result); //===----------------------------------------------------------------------===// // Misc utilities //===----------------------------------------------------------------------===// /// Produce a string describing the given constexpr call. static void describeCall(CallStackFrame *Frame, raw_ostream &Out) { unsigned ArgIndex = 0; bool IsMemberCall = isa(Frame->Callee) && !isa(Frame->Callee) && cast(Frame->Callee)->isInstance(); if (!IsMemberCall) Out << *Frame->Callee << '('; if (Frame->This && IsMemberCall) { APValue Val; Frame->This->moveInto(Val); Val.printPretty(Out, Frame->Info.Ctx, Frame->This->Designator.MostDerivedType); // FIXME: Add parens around Val if needed. Out << "->" << *Frame->Callee << '('; IsMemberCall = false; } for (FunctionDecl::param_const_iterator I = Frame->Callee->param_begin(), E = Frame->Callee->param_end(); I != E; ++I, ++ArgIndex) { if (ArgIndex > (unsigned)IsMemberCall) Out << ", "; const ParmVarDecl *Param = *I; const APValue &Arg = Frame->Arguments[ArgIndex]; Arg.printPretty(Out, Frame->Info.Ctx, Param->getType()); if (ArgIndex == 0 && IsMemberCall) Out << "->" << *Frame->Callee << '('; } Out << ')'; } /// Evaluate an expression to see if it had side-effects, and discard its /// result. /// \return \c true if the caller should keep evaluating. static bool EvaluateIgnoredValue(EvalInfo &Info, const Expr *E) { APValue Scratch; if (!Evaluate(Scratch, Info, E)) // We don't need the value, but we might have skipped a side effect here. return Info.noteSideEffect(); return true; } /// Sign- or zero-extend a value to 64 bits. If it's already 64 bits, just /// return its existing value. static int64_t getExtValue(const APSInt &Value) { return Value.isSigned() ? Value.getSExtValue() : static_cast(Value.getZExtValue()); } /// Should this call expression be treated as a string literal? static bool IsStringLiteralCall(const CallExpr *E) { unsigned Builtin = E->getBuiltinCallee(); return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString || Builtin == Builtin::BI__builtin___NSStringMakeConstantString); } static bool IsGlobalLValue(APValue::LValueBase B) { // C++11 [expr.const]p3 An address constant expression is a prvalue core // constant expression of pointer type that evaluates to... // ... a null pointer value, or a prvalue core constant expression of type // std::nullptr_t. if (!B) return true; if (const ValueDecl *D = B.dyn_cast()) { // ... the address of an object with static storage duration, if (const VarDecl *VD = dyn_cast(D)) return VD->hasGlobalStorage(); // ... the address of a function, return isa(D); } const Expr *E = B.get(); switch (E->getStmtClass()) { default: return false; case Expr::CompoundLiteralExprClass: { const CompoundLiteralExpr *CLE = cast(E); return CLE->isFileScope() && CLE->isLValue(); } case Expr::MaterializeTemporaryExprClass: // A materialized temporary might have been lifetime-extended to static // storage duration. return cast(E)->getStorageDuration() == SD_Static; // A string literal has static storage duration. case Expr::StringLiteralClass: case Expr::PredefinedExprClass: case Expr::ObjCStringLiteralClass: case Expr::ObjCEncodeExprClass: case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: return true; case Expr::CallExprClass: return IsStringLiteralCall(cast(E)); // For GCC compatibility, &&label has static storage duration. case Expr::AddrLabelExprClass: return true; // A Block literal expression may be used as the initialization value for // Block variables at global or local static scope. case Expr::BlockExprClass: return !cast(E)->getBlockDecl()->hasCaptures(); case Expr::ImplicitValueInitExprClass: // FIXME: // We can never form an lvalue with an implicit value initialization as its // base through expression evaluation, so these only appear in one case: the // implicit variable declaration we invent when checking whether a constexpr // constructor can produce a constant expression. We must assume that such // an expression might be a global lvalue. return true; } } static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) { assert(Base && "no location for a null lvalue"); const ValueDecl *VD = Base.dyn_cast(); if (VD) Info.Note(VD->getLocation(), diag::note_declared_at); else Info.Note(Base.get()->getExprLoc(), diag::note_constexpr_temporary_here); } /// Check that this reference or pointer core constant expression is a valid /// value for an address or reference constant expression. Return true if we /// can fold this expression, whether or not it's a constant expression. static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, QualType Type, const LValue &LVal) { bool IsReferenceType = Type->isReferenceType(); APValue::LValueBase Base = LVal.getLValueBase(); const SubobjectDesignator &Designator = LVal.getLValueDesignator(); // Check that the object is a global. Note that the fake 'this' object we // manufacture when checking potential constant expressions is conservatively // assumed to be global here. if (!IsGlobalLValue(Base)) { if (Info.getLangOpts().CPlusPlus11) { const ValueDecl *VD = Base.dyn_cast(); Info.FFDiag(Loc, diag::note_constexpr_non_global, 1) << IsReferenceType << !Designator.Entries.empty() << !!VD << VD; NoteLValueLocation(Info, Base); } else { Info.FFDiag(Loc); } // Don't allow references to temporaries to escape. return false; } assert((Info.checkingPotentialConstantExpression() || LVal.getLValueCallIndex() == 0) && "have call index for global lvalue"); if (const ValueDecl *VD = Base.dyn_cast()) { if (const VarDecl *Var = dyn_cast(VD)) { // Check if this is a thread-local variable. if (Var->getTLSKind()) return false; // A dllimport variable never acts like a constant. if (Var->hasAttr()) return false; } if (const auto *FD = dyn_cast(VD)) { // __declspec(dllimport) must be handled very carefully: // We must never initialize an expression with the thunk in C++. // Doing otherwise would allow the same id-expression to yield // different addresses for the same function in different translation // units. However, this means that we must dynamically initialize the // expression with the contents of the import address table at runtime. // // The C language has no notion of ODR; furthermore, it has no notion of // dynamic initialization. This means that we are permitted to // perform initialization with the address of the thunk. if (Info.getLangOpts().CPlusPlus && FD->hasAttr()) return false; } } // Allow address constant expressions to be past-the-end pointers. This is // an extension: the standard requires them to point to an object. if (!IsReferenceType) return true; // A reference constant expression must refer to an object. if (!Base) { // FIXME: diagnostic Info.CCEDiag(Loc); return true; } // Does this refer one past the end of some object? if (!Designator.Invalid && Designator.isOnePastTheEnd()) { const ValueDecl *VD = Base.dyn_cast(); Info.FFDiag(Loc, diag::note_constexpr_past_end, 1) << !Designator.Entries.empty() << !!VD << VD; NoteLValueLocation(Info, Base); } return true; } /// Check that this core constant expression is of literal type, and if not, /// produce an appropriate diagnostic. static bool CheckLiteralType(EvalInfo &Info, const Expr *E, const LValue *This = nullptr) { if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx)) return true; // C++1y: A constant initializer for an object o [...] may also invoke // constexpr constructors for o and its subobjects even if those objects // are of non-literal class types. // // C++11 missed this detail for aggregates, so classes like this: // struct foo_t { union { int i; volatile int j; } u; }; // are not (obviously) initializable like so: // __attribute__((__require_constant_initialization__)) // static const foo_t x = {{0}}; // because "i" is a subobject with non-literal initialization (due to the // volatile member of the union). See: // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1677 // Therefore, we use the C++1y behavior. if (This && Info.EvaluatingDecl == This->getLValueBase()) return true; // Prvalue constant expressions must be of literal types. if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType(); else Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } /// Check that this core constant expression value is a valid value for a /// constant expression. If not, report an appropriate diagnostic. Does not /// check that the expression is of literal type. static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, QualType Type, const APValue &Value) { if (Value.isUninit()) { Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) << true << Type; return false; } // We allow _Atomic(T) to be initialized from anything that T can be // initialized from. if (const AtomicType *AT = Type->getAs()) Type = AT->getValueType(); // Core issue 1454: For a literal constant expression of array or class type, // each subobject of its value shall have been initialized by a constant // expression. if (Value.isArray()) { QualType EltTy = Type->castAsArrayTypeUnsafe()->getElementType(); for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) { if (!CheckConstantExpression(Info, DiagLoc, EltTy, Value.getArrayInitializedElt(I))) return false; } if (!Value.hasArrayFiller()) return true; return CheckConstantExpression(Info, DiagLoc, EltTy, Value.getArrayFiller()); } if (Value.isUnion() && Value.getUnionField()) { return CheckConstantExpression(Info, DiagLoc, Value.getUnionField()->getType(), Value.getUnionValue()); } if (Value.isStruct()) { RecordDecl *RD = Type->castAs()->getDecl(); if (const CXXRecordDecl *CD = dyn_cast(RD)) { unsigned BaseIndex = 0; for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(), End = CD->bases_end(); I != End; ++I, ++BaseIndex) { if (!CheckConstantExpression(Info, DiagLoc, I->getType(), Value.getStructBase(BaseIndex))) return false; } } for (const auto *I : RD->fields()) { if (!CheckConstantExpression(Info, DiagLoc, I->getType(), Value.getStructField(I->getFieldIndex()))) return false; } } if (Value.isLValue()) { LValue LVal; LVal.setFrom(Info.Ctx, Value); return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal); } // Everything else is fine. return true; } static const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { return LVal.Base.dyn_cast(); } static bool IsLiteralLValue(const LValue &Value) { if (Value.CallIndex) return false; const Expr *E = Value.Base.dyn_cast(); return E && !isa(E); } static bool IsWeakLValue(const LValue &Value) { const ValueDecl *Decl = GetLValueBaseDecl(Value); return Decl && Decl->isWeak(); } static bool isZeroSized(const LValue &Value) { const ValueDecl *Decl = GetLValueBaseDecl(Value); if (Decl && isa(Decl)) { QualType Ty = Decl->getType(); if (Ty->isArrayType()) return Ty->isIncompleteType() || Decl->getASTContext().getTypeSize(Ty) == 0; } return false; } static bool EvalPointerValueAsBool(const APValue &Value, bool &Result) { // A null base expression indicates a null pointer. These are always // evaluatable, and they are false unless the offset is zero. if (!Value.getLValueBase()) { Result = !Value.getLValueOffset().isZero(); return true; } // We have a non-null base. These are generally known to be true, but if it's // a weak declaration it can be null at runtime. Result = true; const ValueDecl *Decl = Value.getLValueBase().dyn_cast(); return !Decl || !Decl->isWeak(); } static bool HandleConversionToBool(const APValue &Val, bool &Result) { switch (Val.getKind()) { case APValue::Uninitialized: return false; case APValue::Int: Result = Val.getInt().getBoolValue(); return true; case APValue::Float: Result = !Val.getFloat().isZero(); return true; case APValue::ComplexInt: Result = Val.getComplexIntReal().getBoolValue() || Val.getComplexIntImag().getBoolValue(); return true; case APValue::ComplexFloat: Result = !Val.getComplexFloatReal().isZero() || !Val.getComplexFloatImag().isZero(); return true; case APValue::LValue: return EvalPointerValueAsBool(Val, Result); case APValue::MemberPointer: Result = Val.getMemberPointerDecl(); return true; case APValue::Vector: case APValue::Array: case APValue::Struct: case APValue::Union: case APValue::AddrLabelDiff: return false; } llvm_unreachable("unknown APValue kind"); } static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result, EvalInfo &Info) { assert(E->isRValue() && "missing lvalue-to-rvalue conv in bool condition"); APValue Val; if (!Evaluate(Val, Info, E)) return false; return HandleConversionToBool(Val, Result); } template static bool HandleOverflow(EvalInfo &Info, const Expr *E, const T &SrcValue, QualType DestType) { Info.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << DestType; return Info.noteUndefinedBehavior(); } static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E, QualType SrcType, const APFloat &Value, QualType DestType, APSInt &Result) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); // Determine whether we are converting to unsigned or signed. bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); Result = APSInt(DestWidth, !DestSigned); bool ignored; if (Value.convertToInteger(Result, llvm::APFloat::rmTowardZero, &ignored) & APFloat::opInvalidOp) return HandleOverflow(Info, E, Value, DestType); return true; } static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, QualType SrcType, QualType DestType, APFloat &Result) { APFloat Value = Result; bool ignored; if (Result.convert(Info.Ctx.getFloatTypeSemantics(DestType), APFloat::rmNearestTiesToEven, &ignored) & APFloat::opOverflow) return HandleOverflow(Info, E, Value, DestType); return true; } static APSInt HandleIntToIntCast(EvalInfo &Info, const Expr *E, QualType DestType, QualType SrcType, const APSInt &Value) { unsigned DestWidth = Info.Ctx.getIntWidth(DestType); APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. Result = Result.extOrTrunc(DestWidth); Result.setIsUnsigned(DestType->isUnsignedIntegerOrEnumerationType()); return Result; } static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, QualType SrcType, const APSInt &Value, QualType DestType, APFloat &Result) { Result = APFloat(Info.Ctx.getFloatTypeSemantics(DestType), 1); if (Result.convertFromAPInt(Value, Value.isSigned(), APFloat::rmNearestTiesToEven) & APFloat::opOverflow) return HandleOverflow(Info, E, Value, DestType); return true; } static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E, APValue &Value, const FieldDecl *FD) { assert(FD->isBitField() && "truncateBitfieldValue on non-bitfield"); if (!Value.isInt()) { // Trying to store a pointer-cast-to-integer into a bitfield. // FIXME: In this case, we should provide the diagnostic for casting // a pointer to an integer. assert(Value.isLValue() && "integral value neither int nor lvalue?"); Info.FFDiag(E); return false; } APSInt &Int = Value.getInt(); unsigned OldBitWidth = Int.getBitWidth(); unsigned NewBitWidth = FD->getBitWidthValue(Info.Ctx); if (NewBitWidth < OldBitWidth) Int = Int.trunc(NewBitWidth).extend(OldBitWidth); return true; } static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E, llvm::APInt &Res) { APValue SVal; if (!Evaluate(SVal, Info, E)) return false; if (SVal.isInt()) { Res = SVal.getInt(); return true; } if (SVal.isFloat()) { Res = SVal.getFloat().bitcastToAPInt(); return true; } if (SVal.isVector()) { QualType VecTy = E->getType(); unsigned VecSize = Info.Ctx.getTypeSize(VecTy); QualType EltTy = VecTy->castAs()->getElementType(); unsigned EltSize = Info.Ctx.getTypeSize(EltTy); bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); Res = llvm::APInt::getNullValue(VecSize); for (unsigned i = 0; i < SVal.getVectorLength(); i++) { APValue &Elt = SVal.getVectorElt(i); llvm::APInt EltAsInt; if (Elt.isInt()) { EltAsInt = Elt.getInt(); } else if (Elt.isFloat()) { EltAsInt = Elt.getFloat().bitcastToAPInt(); } else { // Don't try to handle vectors of anything other than int or float // (not sure if it's possible to hit this case). Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } unsigned BaseEltSize = EltAsInt.getBitWidth(); if (BigEndian) Res |= EltAsInt.zextOrTrunc(VecSize).rotr(i*EltSize+BaseEltSize); else Res |= EltAsInt.zextOrTrunc(VecSize).rotl(i*EltSize); } return true; } // Give up if the input isn't an int, float, or vector. For example, we // reject "(v4i16)(intptr_t)&a". Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } /// Perform the given integer operation, which is known to need at most BitWidth /// bits, and check for overflow in the original type (if that type was not an /// unsigned type). template static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E, const APSInt &LHS, const APSInt &RHS, unsigned BitWidth, Operation Op, APSInt &Result) { if (LHS.isUnsigned()) { Result = Op(LHS, RHS); return true; } APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false); Result = Value.trunc(LHS.getBitWidth()); if (Result.extend(BitWidth) != Value) { if (Info.checkingForOverflow()) Info.Ctx.getDiagnostics().Report(E->getExprLoc(), diag::warn_integer_constant_overflow) << Result.toString(10) << E->getType(); else return HandleOverflow(Info, E, Value, E->getType()); } return true; } /// Perform the given binary integer operation. static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS, BinaryOperatorKind Opcode, APSInt RHS, APSInt &Result) { switch (Opcode) { default: Info.FFDiag(E); return false; case BO_Mul: return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2, std::multiplies(), Result); case BO_Add: return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, std::plus(), Result); case BO_Sub: return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1, std::minus(), Result); case BO_And: Result = LHS & RHS; return true; case BO_Xor: Result = LHS ^ RHS; return true; case BO_Or: Result = LHS | RHS; return true; case BO_Div: case BO_Rem: if (RHS == 0) { Info.FFDiag(E, diag::note_expr_divide_by_zero); return false; } Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS); // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. APSInt supports // this operation and gives the two's complement result. if (RHS.isNegative() && RHS.isAllOnesValue() && LHS.isSigned() && LHS.isMinSignedValue()) return HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E->getType()); return true; case BO_Shl: { if (Info.getLangOpts().OpenCL) // OpenCL 6.3j: shift values are effectively % word size of LHS. RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), static_cast(LHS.getBitWidth() - 1)), RHS.isUnsigned()); else if (RHS.isSigned() && RHS.isNegative()) { // During constant-folding, a negative shift is an opposite shift. Such // a shift is not a constant expression. Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_right; } shift_left: // C++11 [expr.shift]p1: Shift width must be less than the bit width of // the shifted type. unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); if (SA != RHS) { Info.CCEDiag(E, diag::note_constexpr_large_shift) << RHS << E->getType() << LHS.getBitWidth(); } else if (LHS.isSigned()) { // C++11 [expr.shift]p2: A signed left shift must have a non-negative // operand, and must not overflow the corresponding unsigned type. if (LHS.isNegative()) Info.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS; else if (LHS.countLeadingZeros() < SA) Info.CCEDiag(E, diag::note_constexpr_lshift_discards); } Result = LHS << SA; return true; } case BO_Shr: { if (Info.getLangOpts().OpenCL) // OpenCL 6.3j: shift values are effectively % word size of LHS. RHS &= APSInt(llvm::APInt(RHS.getBitWidth(), static_cast(LHS.getBitWidth() - 1)), RHS.isUnsigned()); else if (RHS.isSigned() && RHS.isNegative()) { // During constant-folding, a negative shift is an opposite shift. Such a // shift is not a constant expression. Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS; RHS = -RHS; goto shift_left; } shift_right: // C++11 [expr.shift]p1: Shift width must be less than the bit width of the // shifted type. unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1); if (SA != RHS) Info.CCEDiag(E, diag::note_constexpr_large_shift) << RHS << E->getType() << LHS.getBitWidth(); Result = LHS >> SA; return true; } case BO_LT: Result = LHS < RHS; return true; case BO_GT: Result = LHS > RHS; return true; case BO_LE: Result = LHS <= RHS; return true; case BO_GE: Result = LHS >= RHS; return true; case BO_EQ: Result = LHS == RHS; return true; case BO_NE: Result = LHS != RHS; return true; } } /// Perform the given binary floating-point operation, in-place, on LHS. static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E, APFloat &LHS, BinaryOperatorKind Opcode, const APFloat &RHS) { switch (Opcode) { default: Info.FFDiag(E); return false; case BO_Mul: LHS.multiply(RHS, APFloat::rmNearestTiesToEven); break; case BO_Add: LHS.add(RHS, APFloat::rmNearestTiesToEven); break; case BO_Sub: LHS.subtract(RHS, APFloat::rmNearestTiesToEven); break; case BO_Div: LHS.divide(RHS, APFloat::rmNearestTiesToEven); break; } if (LHS.isInfinity() || LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); return Info.noteUndefinedBehavior(); } return true; } /// Cast an lvalue referring to a base subobject to a derived class, by /// truncating the lvalue's path to the given length. static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result, const RecordDecl *TruncatedType, unsigned TruncatedElements) { SubobjectDesignator &D = Result.Designator; // Check we actually point to a derived class object. if (TruncatedElements == D.Entries.size()) return true; assert(TruncatedElements >= D.MostDerivedPathLength && "not casting to a derived class"); if (!Result.checkSubobject(Info, E, CSK_Derived)) return false; // Truncate the path to the subobject, and remove any derived-to-base offsets. const RecordDecl *RD = TruncatedType; for (unsigned I = TruncatedElements, N = D.Entries.size(); I != N; ++I) { if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); const CXXRecordDecl *Base = getAsBaseClass(D.Entries[I]); if (isVirtualBaseClass(D.Entries[I])) Result.Offset -= Layout.getVBaseClassOffset(Base); else Result.Offset -= Layout.getBaseClassOffset(Base); RD = Base; } D.Entries.resize(TruncatedElements); return true; } static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj, const CXXRecordDecl *Derived, const CXXRecordDecl *Base, const ASTRecordLayout *RL = nullptr) { if (!RL) { if (Derived->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(Derived); } Obj.getLValueOffset() += RL->getBaseClassOffset(Base); Obj.addDecl(Info, E, Base, /*Virtual*/ false); return true; } static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, const CXXRecordDecl *DerivedDecl, const CXXBaseSpecifier *Base) { const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl(); if (!Base->isVirtual()) return HandleLValueDirectBase(Info, E, Obj, DerivedDecl, BaseDecl); SubobjectDesignator &D = Obj.Designator; if (D.Invalid) return false; // Extract most-derived object and corresponding type. DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) return false; // Find the virtual base class. if (DerivedDecl->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl); Obj.getLValueOffset() += Layout.getVBaseClassOffset(BaseDecl); Obj.addDecl(Info, E, BaseDecl, /*Virtual*/ true); return true; } static bool HandleLValueBasePath(EvalInfo &Info, const CastExpr *E, QualType Type, LValue &Result) { for (CastExpr::path_const_iterator PathI = E->path_begin(), PathE = E->path_end(); PathI != PathE; ++PathI) { if (!HandleLValueBase(Info, E, Result, Type->getAsCXXRecordDecl(), *PathI)) return false; Type = (*PathI)->getType(); } return true; } /// Update LVal to refer to the given field, which must be a member of the type /// currently described by LVal. static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal, const FieldDecl *FD, const ASTRecordLayout *RL = nullptr) { if (!RL) { if (FD->getParent()->isInvalidDecl()) return false; RL = &Info.Ctx.getASTRecordLayout(FD->getParent()); } unsigned I = FD->getFieldIndex(); LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I))); LVal.addDecl(Info, E, FD); return true; } /// Update LVal to refer to the given indirect field. static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E, LValue &LVal, const IndirectFieldDecl *IFD) { for (const auto *C : IFD->chain()) if (!HandleLValueMember(Info, E, LVal, cast(C))) return false; return true; } /// Get the size of the given type in char units. static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc, QualType Type, CharUnits &Size) { // sizeof(void), __alignof__(void), sizeof(function) = 1 as a gcc // extension. if (Type->isVoidType() || Type->isFunctionType()) { Size = CharUnits::One(); return true; } if (Type->isDependentType()) { Info.FFDiag(Loc); return false; } if (!Type->isConstantSizeType()) { // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. // FIXME: Better diagnostic. Info.FFDiag(Loc); return false; } Size = Info.Ctx.getTypeSizeInChars(Type); return true; } /// Update a pointer value to model pointer arithmetic. /// \param Info - Information about the ongoing evaluation. /// \param E - The expression being evaluated, for diagnostic purposes. /// \param LVal - The pointer value to be updated. /// \param EltTy - The pointee type represented by LVal. /// \param Adjustment - The adjustment, in objects of type EltTy, to add. static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E, LValue &LVal, QualType EltTy, int64_t Adjustment) { CharUnits SizeOfPointee; if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee)) return false; LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee); return true; } /// Update an lvalue to refer to a component of a complex number. /// \param Info - Information about the ongoing evaluation. /// \param LVal - The lvalue to be updated. /// \param EltTy - The complex number's component type. /// \param Imag - False for the real component, true for the imaginary. static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E, LValue &LVal, QualType EltTy, bool Imag) { if (Imag) { CharUnits SizeOfComponent; if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfComponent)) return false; LVal.Offset += SizeOfComponent; } LVal.addComplex(Info, E, EltTy, Imag); return true; } /// Try to evaluate the initializer for a variable declaration. /// /// \param Info Information about the ongoing evaluation. /// \param E An expression to be used when printing diagnostics. /// \param VD The variable whose initializer should be obtained. /// \param Frame The frame in which the variable was created. Must be null /// if this variable is not local to the evaluation. /// \param Result Filled in with a pointer to the value of the variable. static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, const VarDecl *VD, CallStackFrame *Frame, APValue *&Result) { // If this is a parameter to an active constexpr function call, perform // argument substitution. if (const ParmVarDecl *PVD = dyn_cast(VD)) { // Assume arguments of a potential constant expression are unknown // constant expressions. if (Info.checkingPotentialConstantExpression()) return false; if (!Frame || !Frame->Arguments) { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = &Frame->Arguments[PVD->getFunctionScopeIndex()]; return true; } // If this is a local variable, dig out its value. if (Frame) { Result = Frame->getTemporary(VD); if (!Result) { // Assume variables referenced within a lambda's call operator that were // not declared within the call operator are captures and during checking // of a potential constant expression, assume they are unknown constant // expressions. assert(isLambdaCallOperator(Frame->Callee) && (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) && "missing value for local variable"); if (Info.checkingPotentialConstantExpression()) return false; // FIXME: implement capture evaluation during constant expr evaluation. Info.FFDiag(E->getLocStart(), diag::note_unimplemented_constexpr_lambda_feature_ast) << "captures not currently allowed"; return false; } return true; } // Dig out the initializer, and use the declaration which it's attached to. const Expr *Init = VD->getAnyInitializer(VD); if (!Init || Init->isValueDependent()) { // If we're checking a potential constant expression, the variable could be // initialized later. if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } // If we're currently evaluating the initializer of this declaration, use that // in-flight value. if (Info.EvaluatingDecl.dyn_cast() == VD) { Result = Info.EvaluatingDeclValue; return true; } // Never evaluate the initializer of a weak variable. We can't be sure that // this is the definition which will be used. if (VD->isWeak()) { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } // Check that we can fold the initializer. In C++, we will have already done // this in the cases where it matters for conformance. SmallVector Notes; if (!VD->evaluateValue(Notes)) { Info.FFDiag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); Info.addNotes(Notes); return false; } else if (!VD->checkInitIsICE()) { Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); Info.addNotes(Notes); } Result = VD->getEvaluatedValue(); return true; } static bool IsConstNonVolatile(QualType T) { Qualifiers Quals = T.getQualifiers(); return Quals.hasConst() && !Quals.hasVolatile(); } /// Get the base index of the given base class within an APValue representing /// the given derived class. static unsigned getBaseIndex(const CXXRecordDecl *Derived, const CXXRecordDecl *Base) { Base = Base->getCanonicalDecl(); unsigned Index = 0; for (CXXRecordDecl::base_class_const_iterator I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I, ++Index) { if (I->getType()->getAsCXXRecordDecl()->getCanonicalDecl() == Base) return Index; } llvm_unreachable("base class missing from derived class's bases list"); } /// Extract the value of a character from a string literal. static APSInt extractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit, uint64_t Index) { // FIXME: Support MakeStringConstant if (const auto *ObjCEnc = dyn_cast(Lit)) { std::string Str; Info.Ctx.getObjCEncodingForType(ObjCEnc->getEncodedType(), Str); assert(Index <= Str.size() && "Index too large"); return APSInt::getUnsigned(Str.c_str()[Index]); } if (auto PE = dyn_cast(Lit)) Lit = PE->getFunctionName(); const StringLiteral *S = cast(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); assert(CAT && "string literal isn't an array"); QualType CharType = CAT->getElementType(); assert(CharType->isIntegerType() && "unexpected character type"); APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), CharType->isUnsignedIntegerType()); if (Index < S->getLength()) Value = S->getCodeUnit(Index); return Value; } // Expand a string literal into an array of characters. static void expandStringLiteral(EvalInfo &Info, const Expr *Lit, APValue &Result) { const StringLiteral *S = cast(Lit); const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(S->getType()); assert(CAT && "string literal isn't an array"); QualType CharType = CAT->getElementType(); assert(CharType->isIntegerType() && "unexpected character type"); unsigned Elts = CAT->getSize().getZExtValue(); Result = APValue(APValue::UninitArray(), std::min(S->getLength(), Elts), Elts); APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(), CharType->isUnsignedIntegerType()); if (Result.hasArrayFiller()) Result.getArrayFiller() = APValue(Value); for (unsigned I = 0, N = Result.getArrayInitializedElts(); I != N; ++I) { Value = S->getCodeUnit(I); Result.getArrayInitializedElt(I) = APValue(Value); } } // Expand an array so that it has more than Index filled elements. static void expandArray(APValue &Array, unsigned Index) { unsigned Size = Array.getArraySize(); assert(Index < Size); // Always at least double the number of elements for which we store a value. unsigned OldElts = Array.getArrayInitializedElts(); unsigned NewElts = std::max(Index+1, OldElts * 2); NewElts = std::min(Size, std::max(NewElts, 8u)); // Copy the data across. APValue NewValue(APValue::UninitArray(), NewElts, Size); for (unsigned I = 0; I != OldElts; ++I) NewValue.getArrayInitializedElt(I).swap(Array.getArrayInitializedElt(I)); for (unsigned I = OldElts; I != NewElts; ++I) NewValue.getArrayInitializedElt(I) = Array.getArrayFiller(); if (NewValue.hasArrayFiller()) NewValue.getArrayFiller() = Array.getArrayFiller(); Array.swap(NewValue); } /// Determine whether a type would actually be read by an lvalue-to-rvalue /// conversion. If it's of class type, we may assume that the copy operation /// is trivial. Note that this is never true for a union type with fields /// (because the copy always "reads" the active member) and always true for /// a non-class type. static bool isReadByLvalueToRvalueConversion(QualType T) { CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); if (!RD || (RD->isUnion() && !RD->field_empty())) return true; if (RD->isEmpty()) return false; for (auto *Field : RD->fields()) if (isReadByLvalueToRvalueConversion(Field->getType())) return true; for (auto &BaseSpec : RD->bases()) if (isReadByLvalueToRvalueConversion(BaseSpec.getType())) return true; return false; } /// Diagnose an attempt to read from any unreadable field within the specified /// type, which might be a class type. static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E, QualType T) { CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); if (!RD) return false; if (!RD->hasMutableFields()) return false; for (auto *Field : RD->fields()) { // If we're actually going to read this field in some way, then it can't // be mutable. If we're in a union, then assigning to a mutable field // (even an empty one) can change the active member, so that's not OK. // FIXME: Add core issue number for the union case. if (Field->isMutable() && (RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) { Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1) << Field; Info.Note(Field->getLocation(), diag::note_declared_at); return true; } if (diagnoseUnreadableFields(Info, E, Field->getType())) return true; } for (auto &BaseSpec : RD->bases()) if (diagnoseUnreadableFields(Info, E, BaseSpec.getType())) return true; // All mutable fields were empty, and thus not actually read. return false; } /// Kinds of access we can perform on an object, for diagnostics. enum AccessKinds { AK_Read, AK_Assign, AK_Increment, AK_Decrement }; namespace { /// A handle to a complete object (an object that is not a subobject of /// another object). struct CompleteObject { /// The value of the complete object. APValue *Value; /// The type of the complete object. QualType Type; CompleteObject() : Value(nullptr) {} CompleteObject(APValue *Value, QualType Type) : Value(Value), Type(Type) { assert(Value && "missing value for complete object"); } explicit operator bool() const { return Value; } }; } // end anonymous namespace /// Find the designated sub-object of an rvalue. template typename SubobjectHandler::result_type findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const SubobjectDesignator &Sub, SubobjectHandler &handler) { if (Sub.Invalid) // A diagnostic will have already been produced. return handler.failed(); if (Sub.isOnePastTheEnd()) { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else Info.FFDiag(E); return handler.failed(); } APValue *O = Obj.Value; QualType ObjType = Obj.Type; const FieldDecl *LastField = nullptr; // Walk the designator's path to find the subobject. for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { if (O->isUninit()) { if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_constexpr_access_uninit) << handler.AccessKind; return handler.failed(); } if (I == N) { // If we are reading an object of class type, there may still be more // things we need to check: if there are any mutable subobjects, we // cannot perform this read. (This only happens when performing a trivial // copy or assignment.) if (ObjType->isRecordType() && handler.AccessKind == AK_Read && diagnoseUnreadableFields(Info, E, ObjType)) return handler.failed(); if (!handler.found(*O, ObjType)) return false; // If we modified a bit-field, truncate it to the right width. if (handler.AccessKind != AK_Read && LastField && LastField->isBitField() && !truncateBitfieldValue(Info, E, *O, LastField)) return false; return true; } LastField = nullptr; if (ObjType->isArrayType()) { // Next subobject is an array element. const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); assert(CAT && "vla in literal type?"); uint64_t Index = Sub.Entries[I].ArrayIndex; if (CAT->getSize().ule(Index)) { // Note, it should not be possible to form a pointer with a valid // designator which points more than one past the end of the array. if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else Info.FFDiag(E); return handler.failed(); } ObjType = CAT->getElementType(); // An array object is represented as either an Array APValue or as an // LValue which refers to a string literal. if (O->isLValue()) { assert(I == N - 1 && "extracting subobject of character?"); assert(!O->hasLValuePath() || O->getLValuePath().empty()); if (handler.AccessKind != AK_Read) expandStringLiteral(Info, O->getLValueBase().get(), *O); else return handler.foundString(*O, ObjType, Index); } if (O->getArrayInitializedElts() > Index) O = &O->getArrayInitializedElt(Index); else if (handler.AccessKind != AK_Read) { expandArray(*O, Index); O = &O->getArrayInitializedElt(Index); } else O = &O->getArrayFiller(); } else if (ObjType->isAnyComplexType()) { // Next subobject is a complex number. uint64_t Index = Sub.Entries[I].ArrayIndex; if (Index > 1) { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_access_past_end) << handler.AccessKind; else Info.FFDiag(E); return handler.failed(); } bool WasConstQualified = ObjType.isConstQualified(); ObjType = ObjType->castAs()->getElementType(); if (WasConstQualified) ObjType.addConst(); assert(I == N - 1 && "extracting subobject of scalar?"); if (O->isComplexInt()) { return handler.found(Index ? O->getComplexIntImag() : O->getComplexIntReal(), ObjType); } else { assert(O->isComplexFloat()); return handler.found(Index ? O->getComplexFloatImag() : O->getComplexFloatReal(), ObjType); } } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { if (Field->isMutable() && handler.AccessKind == AK_Read) { Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1) << Field; Info.Note(Field->getLocation(), diag::note_declared_at); return handler.failed(); } // Next subobject is a class, struct or union field. RecordDecl *RD = ObjType->castAs()->getDecl(); if (RD->isUnion()) { const FieldDecl *UnionField = O->getUnionField(); if (!UnionField || UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) { Info.FFDiag(E, diag::note_constexpr_access_inactive_union_member) << handler.AccessKind << Field << !UnionField << UnionField; return handler.failed(); } O = &O->getUnionValue(); } else O = &O->getStructField(Field->getFieldIndex()); bool WasConstQualified = ObjType.isConstQualified(); ObjType = Field->getType(); if (WasConstQualified && !Field->isMutable()) ObjType.addConst(); if (ObjType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { // FIXME: Include a description of the path to the volatile subobject. Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << handler.AccessKind << 2 << Field; Info.Note(Field->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); } return handler.failed(); } LastField = Field; } else { // Next subobject is a base class. const CXXRecordDecl *Derived = ObjType->getAsCXXRecordDecl(); const CXXRecordDecl *Base = getAsBaseClass(Sub.Entries[I]); O = &O->getStructBase(getBaseIndex(Derived, Base)); bool WasConstQualified = ObjType.isConstQualified(); ObjType = Info.Ctx.getRecordType(Base); if (WasConstQualified) ObjType.addConst(); } } } namespace { struct ExtractSubobjectHandler { EvalInfo &Info; APValue &Result; static const AccessKinds AccessKind = AK_Read; typedef bool result_type; bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { Result = Subobj; return true; } bool found(APSInt &Value, QualType SubobjType) { Result = APValue(Value); return true; } bool found(APFloat &Value, QualType SubobjType) { Result = APValue(Value); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { Result = APValue(extractStringLiteralCharacter( Info, Subobj.getLValueBase().get(), Character)); return true; } }; } // end anonymous namespace const AccessKinds ExtractSubobjectHandler::AccessKind; /// Extract the designated sub-object of an rvalue. static bool extractSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const SubobjectDesignator &Sub, APValue &Result) { ExtractSubobjectHandler Handler = { Info, Result }; return findSubobject(Info, E, Obj, Sub, Handler); } namespace { struct ModifySubobjectHandler { EvalInfo &Info; APValue &NewVal; const Expr *E; typedef bool result_type; static const AccessKinds AccessKind = AK_Assign; bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; } bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { if (!checkConst(SubobjType)) return false; // We've been given ownership of NewVal, so just swap it in. Subobj.swap(NewVal); return true; } bool found(APSInt &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (!NewVal.isInt()) { // Maybe trying to write a cast pointer value into a complex? Info.FFDiag(E); return false; } Value = NewVal.getInt(); return true; } bool found(APFloat &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; Value = NewVal.getFloat(); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { llvm_unreachable("shouldn't encounter string elements with ExpandArrays"); } }; } // end anonymous namespace const AccessKinds ModifySubobjectHandler::AccessKind; /// Update the designated sub-object of an rvalue to the given value. static bool modifySubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const SubobjectDesignator &Sub, APValue &NewVal) { ModifySubobjectHandler Handler = { Info, NewVal, E }; return findSubobject(Info, E, Obj, Sub, Handler); } /// Find the position where two subobject designators diverge, or equivalently /// the length of the common initial subsequence. static unsigned FindDesignatorMismatch(QualType ObjType, const SubobjectDesignator &A, const SubobjectDesignator &B, bool &WasArrayIndex) { unsigned I = 0, N = std::min(A.Entries.size(), B.Entries.size()); for (/**/; I != N; ++I) { if (!ObjType.isNull() && (ObjType->isArrayType() || ObjType->isAnyComplexType())) { // Next subobject is an array element. if (A.Entries[I].ArrayIndex != B.Entries[I].ArrayIndex) { WasArrayIndex = true; return I; } if (ObjType->isAnyComplexType()) ObjType = ObjType->castAs()->getElementType(); else ObjType = ObjType->castAsArrayTypeUnsafe()->getElementType(); } else { if (A.Entries[I].BaseOrMember != B.Entries[I].BaseOrMember) { WasArrayIndex = false; return I; } if (const FieldDecl *FD = getAsField(A.Entries[I])) // Next subobject is a field. ObjType = FD->getType(); else // Next subobject is a base class. ObjType = QualType(); } } WasArrayIndex = false; return I; } /// Determine whether the given subobject designators refer to elements of the /// same array object. static bool AreElementsOfSameArray(QualType ObjType, const SubobjectDesignator &A, const SubobjectDesignator &B) { if (A.Entries.size() != B.Entries.size()) return false; bool IsArray = A.MostDerivedIsArrayElement; if (IsArray && A.MostDerivedPathLength != A.Entries.size()) // A is a subobject of the array element. return false; // If A (and B) designates an array element, the last entry will be the array // index. That doesn't have to match. Otherwise, we're in the 'implicit array // of length 1' case, and the entire path must match. bool WasArrayIndex; unsigned CommonLength = FindDesignatorMismatch(ObjType, A, B, WasArrayIndex); return CommonLength >= A.Entries.size() - IsArray; } /// Find the complete object to which an LValue refers. static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK, const LValue &LVal, QualType LValType) { if (!LVal.Base) { Info.FFDiag(E, diag::note_constexpr_access_null) << AK; return CompleteObject(); } CallStackFrame *Frame = nullptr; if (LVal.CallIndex) { Frame = Info.getCallFrame(LVal.CallIndex); if (!Frame) { Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1) << AK << LVal.Base.is(); NoteLValueLocation(Info, LVal.Base); return CompleteObject(); } } // C++11 DR1311: An lvalue-to-rvalue conversion on a volatile-qualified type // is not a constant expression (even if the object is non-volatile). We also // apply this rule to C++98, in order to conform to the expected 'volatile' // semantics. if (LValType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) Info.FFDiag(E, diag::note_constexpr_access_volatile_type) << AK << LValType; else Info.FFDiag(E); return CompleteObject(); } // Compute value storage location and type of base object. APValue *BaseVal = nullptr; QualType BaseType = getType(LVal.Base); if (const ValueDecl *D = LVal.Base.dyn_cast()) { // In C++98, const, non-volatile integers initialized with ICEs are ICEs. // In C++11, constexpr, non-volatile variables initialized with constant // expressions are constant expressions too. Inside constexpr functions, // parameters are constant expressions even if they're non-const. // In C++1y, objects local to a constant expression (those with a Frame) are // both readable and writable inside constant expressions. // In C, such things can also be folded, although they are not ICEs. const VarDecl *VD = dyn_cast(D); if (VD) { if (const VarDecl *VDef = VD->getDefinition(Info.Ctx)) VD = VDef; } if (!VD || VD->isInvalidDecl()) { Info.FFDiag(E); return CompleteObject(); } // Accesses of volatile-qualified objects are not allowed. if (BaseType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << AK << 1 << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E); } return CompleteObject(); } // Unless we're looking at a local variable or argument in a constexpr call, // the variable we're reading must be const. if (!Frame) { if (Info.getLangOpts().CPlusPlus14 && VD == Info.EvaluatingDecl.dyn_cast()) { // OK, we can read and modify an object if we're in the process of // evaluating its initializer, because its lifetime began in this // evaluation. } else if (AK != AK_Read) { // All the remaining cases only permit reading. Info.FFDiag(E, diag::note_constexpr_modify_global); return CompleteObject(); } else if (VD->isConstexpr()) { // OK, we can read this variable. } else if (BaseType->isIntegralOrEnumerationType()) { // In OpenCL if a variable is in constant address space it is a const value. if (!(BaseType.isConstQualified() || (Info.getLangOpts().OpenCL && BaseType.getAddressSpace() == LangAS::opencl_constant))) { if (Info.getLangOpts().CPlusPlus) { Info.FFDiag(E, diag::note_constexpr_ltor_non_const_int, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E); } return CompleteObject(); } } else if (BaseType->isFloatingType() && BaseType.isConstQualified()) { // We support folding of const floating-point types, in order to make // static const data members of such types (supported as an extension) // more useful. if (Info.getLangOpts().CPlusPlus11) { Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.CCEDiag(E); } } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) { Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD; // Keep evaluating to see what we can do. } else { // FIXME: Allow folding of values of any literal type in all languages. if (Info.checkingPotentialConstantExpression() && VD->getType().isConstQualified() && !VD->hasDefinition(Info.Ctx)) { // The definition of this variable could be constexpr. We can't // access it right now, but may be able to in future. } else if (Info.getLangOpts().CPlusPlus11) { Info.FFDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { Info.FFDiag(E); } return CompleteObject(); } } if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal)) return CompleteObject(); } else { const Expr *Base = LVal.Base.dyn_cast(); if (!Frame) { if (const MaterializeTemporaryExpr *MTE = dyn_cast(Base)) { assert(MTE->getStorageDuration() == SD_Static && "should have a frame for a non-global materialized temporary"); // Per C++1y [expr.const]p2: // an lvalue-to-rvalue conversion [is not allowed unless it applies to] // - a [...] glvalue of integral or enumeration type that refers to // a non-volatile const object [...] // [...] // - a [...] glvalue of literal type that refers to a non-volatile // object whose lifetime began within the evaluation of e. // // C++11 misses the 'began within the evaluation of e' check and // instead allows all temporaries, including things like: // int &&r = 1; // int x = ++r; // constexpr int k = r; // Therefore we use the C++1y rules in C++11 too. const ValueDecl *VD = Info.EvaluatingDecl.dyn_cast(); const ValueDecl *ED = MTE->getExtendingDecl(); if (!(BaseType.isConstQualified() && BaseType->isIntegralOrEnumerationType()) && !(VD && VD->getCanonicalDecl() == ED->getCanonicalDecl())) { Info.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK; Info.Note(MTE->getExprLoc(), diag::note_constexpr_temporary_here); return CompleteObject(); } BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false); assert(BaseVal && "got reference to unevaluated temporary"); } else { Info.FFDiag(E); return CompleteObject(); } } else { BaseVal = Frame->getTemporary(Base); assert(BaseVal && "missing value for temporary"); } // Volatile temporary objects cannot be accessed in constant expressions. if (BaseType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1) << AK << 0; Info.Note(Base->getExprLoc(), diag::note_constexpr_temporary_here); } else { Info.FFDiag(E); } return CompleteObject(); } } // During the construction of an object, it is not yet 'const'. // FIXME: We don't set up EvaluatingDecl for local variables or temporaries, // and this doesn't do quite the right thing for const subobjects of the // object under construction. if (LVal.getLValueBase() == Info.EvaluatingDecl) { BaseType = Info.Ctx.getCanonicalType(BaseType); BaseType.removeLocalConst(); } // In C++1y, we can't safely access any mutable state when we might be // evaluating after an unmodeled side effect. // // FIXME: Not all local state is mutable. Allow local constant subobjects // to be read here (but take care with 'mutable' fields). if ((Frame && Info.getLangOpts().CPlusPlus14 && Info.EvalStatus.HasSideEffects) || (AK != AK_Read && Info.IsSpeculativelyEvaluating)) return CompleteObject(); return CompleteObject(BaseVal, BaseType); } /// \brief Perform an lvalue-to-rvalue conversion on the given glvalue. This /// can also be used for 'lvalue-to-lvalue' conversions for looking up the /// glvalue referred to by an entity of reference type. /// /// \param Info - Information about the ongoing evaluation. /// \param Conv - The expression for which we are performing the conversion. /// Used for diagnostics. /// \param Type - The type of the glvalue (before stripping cv-qualifiers in the /// case of a non-class type). /// \param LVal - The glvalue on which we are attempting to perform this action. /// \param RVal - The produced value will be placed here. static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, QualType Type, const LValue &LVal, APValue &RVal) { if (LVal.Designator.Invalid) return false; // Check for special cases where there is no existing APValue to look at. const Expr *Base = LVal.Base.dyn_cast(); if (Base && !LVal.CallIndex && !Type.isVolatileQualified()) { if (const CompoundLiteralExpr *CLE = dyn_cast(Base)) { // In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the // initializer until now for such expressions. Such an expression can't be // an ICE in C, so this only matters for fold. if (Type.isVolatileQualified()) { Info.FFDiag(Conv); return false; } APValue Lit; if (!Evaluate(Lit, Info, CLE->getInitializer())) return false; CompleteObject LitObj(&Lit, Base->getType()); return extractSubobject(Info, Conv, LitObj, LVal.Designator, RVal); } else if (isa(Base) || isa(Base)) { // We represent a string literal array as an lvalue pointing at the // corresponding expression, rather than building an array of chars. // FIXME: Support ObjCEncodeExpr, MakeStringConstant APValue Str(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0); CompleteObject StrObj(&Str, Base->getType()); return extractSubobject(Info, Conv, StrObj, LVal.Designator, RVal); } } CompleteObject Obj = findCompleteObject(Info, Conv, AK_Read, LVal, Type); return Obj && extractSubobject(Info, Conv, Obj, LVal.Designator, RVal); } /// Perform an assignment of Val to LVal. Takes ownership of Val. static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal, QualType LValType, APValue &Val) { if (LVal.Designator.Invalid) return false; if (!Info.getLangOpts().CPlusPlus14) { Info.FFDiag(E); return false; } CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); return Obj && modifySubobject(Info, E, Obj, LVal.Designator, Val); } static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) { return T->isSignedIntegerType() && Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy); } namespace { struct CompoundAssignSubobjectHandler { EvalInfo &Info; const Expr *E; QualType PromotedLHSType; BinaryOperatorKind Opcode; const APValue &RHS; static const AccessKinds AccessKind = AK_Assign; typedef bool result_type; bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; } bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { switch (Subobj.getKind()) { case APValue::Int: return found(Subobj.getInt(), SubobjType); case APValue::Float: return found(Subobj.getFloat(), SubobjType); case APValue::ComplexInt: case APValue::ComplexFloat: // FIXME: Implement complex compound assignment. Info.FFDiag(E); return false; case APValue::LValue: return foundPointer(Subobj, SubobjType); default: // FIXME: can this happen? Info.FFDiag(E); return false; } } bool found(APSInt &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (!SubobjType->isIntegerType() || !RHS.isInt()) { // We don't support compound assignment on integer-cast-to-pointer // values. Info.FFDiag(E); return false; } APSInt LHS = HandleIntToIntCast(Info, E, PromotedLHSType, SubobjType, Value); if (!handleIntIntBinOp(Info, E, LHS, Opcode, RHS.getInt(), LHS)) return false; Value = HandleIntToIntCast(Info, E, SubobjType, PromotedLHSType, LHS); return true; } bool found(APFloat &Value, QualType SubobjType) { return checkConst(SubobjType) && HandleFloatToFloatCast(Info, E, SubobjType, PromotedLHSType, Value) && handleFloatFloatBinOp(Info, E, Value, Opcode, RHS.getFloat()) && HandleFloatToFloatCast(Info, E, PromotedLHSType, SubobjType, Value); } bool foundPointer(APValue &Subobj, QualType SubobjType) { if (!checkConst(SubobjType)) return false; QualType PointeeType; if (const PointerType *PT = SubobjType->getAs()) PointeeType = PT->getPointeeType(); if (PointeeType.isNull() || !RHS.isInt() || (Opcode != BO_Add && Opcode != BO_Sub)) { Info.FFDiag(E); return false; } int64_t Offset = getExtValue(RHS.getInt()); if (Opcode == BO_Sub) Offset = -Offset; LValue LVal; LVal.setFrom(Info.Ctx, Subobj); if (!HandleLValueArrayAdjustment(Info, E, LVal, PointeeType, Offset)) return false; LVal.moveInto(Subobj); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { llvm_unreachable("shouldn't encounter string elements here"); } }; } // end anonymous namespace const AccessKinds CompoundAssignSubobjectHandler::AccessKind; /// Perform a compound assignment of LVal = RVal. static bool handleCompoundAssignment( EvalInfo &Info, const Expr *E, const LValue &LVal, QualType LValType, QualType PromotedLValType, BinaryOperatorKind Opcode, const APValue &RVal) { if (LVal.Designator.Invalid) return false; if (!Info.getLangOpts().CPlusPlus14) { Info.FFDiag(E); return false; } CompleteObject Obj = findCompleteObject(Info, E, AK_Assign, LVal, LValType); CompoundAssignSubobjectHandler Handler = { Info, E, PromotedLValType, Opcode, RVal }; return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); } namespace { struct IncDecSubobjectHandler { EvalInfo &Info; const Expr *E; AccessKinds AccessKind; APValue *Old; typedef bool result_type; bool checkConst(QualType QT) { // Assigning to a const object has undefined behavior. if (QT.isConstQualified()) { Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; return false; } return true; } bool failed() { return false; } bool found(APValue &Subobj, QualType SubobjType) { // Stash the old value. Also clear Old, so we don't clobber it later // if we're post-incrementing a complex. if (Old) { *Old = Subobj; Old = nullptr; } switch (Subobj.getKind()) { case APValue::Int: return found(Subobj.getInt(), SubobjType); case APValue::Float: return found(Subobj.getFloat(), SubobjType); case APValue::ComplexInt: return found(Subobj.getComplexIntReal(), SubobjType->castAs()->getElementType() .withCVRQualifiers(SubobjType.getCVRQualifiers())); case APValue::ComplexFloat: return found(Subobj.getComplexFloatReal(), SubobjType->castAs()->getElementType() .withCVRQualifiers(SubobjType.getCVRQualifiers())); case APValue::LValue: return foundPointer(Subobj, SubobjType); default: // FIXME: can this happen? Info.FFDiag(E); return false; } } bool found(APSInt &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (!SubobjType->isIntegerType()) { // We don't support increment / decrement on integer-cast-to-pointer // values. Info.FFDiag(E); return false; } if (Old) *Old = APValue(Value); // bool arithmetic promotes to int, and the conversion back to bool // doesn't reduce mod 2^n, so special-case it. if (SubobjType->isBooleanType()) { if (AccessKind == AK_Increment) Value = 1; else Value = !Value; return true; } bool WasNegative = Value.isNegative(); if (AccessKind == AK_Increment) { ++Value; if (!WasNegative && Value.isNegative() && isOverflowingIntegerType(Info.Ctx, SubobjType)) { APSInt ActualValue(Value, /*IsUnsigned*/true); return HandleOverflow(Info, E, ActualValue, SubobjType); } } else { --Value; if (WasNegative && !Value.isNegative() && isOverflowingIntegerType(Info.Ctx, SubobjType)) { unsigned BitWidth = Value.getBitWidth(); APSInt ActualValue(Value.sext(BitWidth + 1), /*IsUnsigned*/false); ActualValue.setBit(BitWidth); return HandleOverflow(Info, E, ActualValue, SubobjType); } } return true; } bool found(APFloat &Value, QualType SubobjType) { if (!checkConst(SubobjType)) return false; if (Old) *Old = APValue(Value); APFloat One(Value.getSemantics(), 1); if (AccessKind == AK_Increment) Value.add(One, APFloat::rmNearestTiesToEven); else Value.subtract(One, APFloat::rmNearestTiesToEven); return true; } bool foundPointer(APValue &Subobj, QualType SubobjType) { if (!checkConst(SubobjType)) return false; QualType PointeeType; if (const PointerType *PT = SubobjType->getAs()) PointeeType = PT->getPointeeType(); else { Info.FFDiag(E); return false; } LValue LVal; LVal.setFrom(Info.Ctx, Subobj); if (!HandleLValueArrayAdjustment(Info, E, LVal, PointeeType, AccessKind == AK_Increment ? 1 : -1)) return false; LVal.moveInto(Subobj); return true; } bool foundString(APValue &Subobj, QualType SubobjType, uint64_t Character) { llvm_unreachable("shouldn't encounter string elements here"); } }; } // end anonymous namespace /// Perform an increment or decrement on LVal. static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal, QualType LValType, bool IsIncrement, APValue *Old) { if (LVal.Designator.Invalid) return false; if (!Info.getLangOpts().CPlusPlus14) { Info.FFDiag(E); return false; } AccessKinds AK = IsIncrement ? AK_Increment : AK_Decrement; CompleteObject Obj = findCompleteObject(Info, E, AK, LVal, LValType); IncDecSubobjectHandler Handler = { Info, E, AK, Old }; return Obj && findSubobject(Info, E, Obj, LVal.Designator, Handler); } /// Build an lvalue for the object argument of a member function call. static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, LValue &This) { if (Object->getType()->isPointerType()) return EvaluatePointer(Object, This, Info); if (Object->isGLValue()) return EvaluateLValue(Object, This, Info); if (Object->getType()->isLiteralType(Info.Ctx)) return EvaluateTemporary(Object, This, Info); Info.FFDiag(Object, diag::note_constexpr_nonliteral) << Object->getType(); return false; } /// HandleMemberPointerAccess - Evaluate a member access operation and build an /// lvalue referring to the result. /// /// \param Info - Information about the ongoing evaluation. /// \param LV - An lvalue referring to the base of the member pointer. /// \param RHS - The member pointer expression. /// \param IncludeMember - Specifies whether the member itself is included in /// the resulting LValue subobject designator. This is not possible when /// creating a bound member function. /// \return The field or method declaration to which the member pointer refers, /// or 0 if evaluation fails. static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, QualType LVType, LValue &LV, const Expr *RHS, bool IncludeMember = true) { MemberPtr MemPtr; if (!EvaluateMemberPointer(RHS, MemPtr, Info)) return nullptr; // C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to // member value, the behavior is undefined. if (!MemPtr.getDecl()) { // FIXME: Specific diagnostic. Info.FFDiag(RHS); return nullptr; } if (MemPtr.isDerivedMember()) { // This is a member of some derived class. Truncate LV appropriately. // The end of the derived-to-base path for the base object must match the // derived-to-base path for the member pointer. if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() > LV.Designator.Entries.size()) { Info.FFDiag(RHS); return nullptr; } unsigned PathLengthToMember = LV.Designator.Entries.size() - MemPtr.Path.size(); for (unsigned I = 0, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *LVDecl = getAsBaseClass( LV.Designator.Entries[PathLengthToMember + I]); const CXXRecordDecl *MPDecl = MemPtr.Path[I]; if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) { Info.FFDiag(RHS); return nullptr; } } // Truncate the lvalue to the appropriate derived class. if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(), PathLengthToMember)) return nullptr; } else if (!MemPtr.Path.empty()) { // Extend the LValue path with the member pointer's path. LV.Designator.Entries.reserve(LV.Designator.Entries.size() + MemPtr.Path.size() + IncludeMember); // Walk down to the appropriate base class. if (const PointerType *PT = LVType->getAs()) LVType = PT->getPointeeType(); const CXXRecordDecl *RD = LVType->getAsCXXRecordDecl(); assert(RD && "member pointer access on non-class-type expression"); // The first class in the path is that of the lvalue. for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) { const CXXRecordDecl *Base = MemPtr.Path[N - I - 1]; if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base)) return nullptr; RD = Base; } // Finally cast to the class containing the member. if (!HandleLValueDirectBase(Info, RHS, LV, RD, MemPtr.getContainingRecord())) return nullptr; } // Add the member. Note that we cannot build bound member functions here. if (IncludeMember) { if (const FieldDecl *FD = dyn_cast(MemPtr.getDecl())) { if (!HandleLValueMember(Info, RHS, LV, FD)) return nullptr; } else if (const IndirectFieldDecl *IFD = dyn_cast(MemPtr.getDecl())) { if (!HandleLValueIndirectMember(Info, RHS, LV, IFD)) return nullptr; } else { llvm_unreachable("can't construct reference to bound member function"); } } return MemPtr.getDecl(); } static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info, const BinaryOperator *BO, LValue &LV, bool IncludeMember = true) { assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI); if (!EvaluateObjectArgument(Info, BO->getLHS(), LV)) { if (Info.noteFailure()) { MemberPtr MemPtr; EvaluateMemberPointer(BO->getRHS(), MemPtr, Info); } return nullptr; } return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV, BO->getRHS(), IncludeMember); } /// HandleBaseToDerivedCast - Apply the given base-to-derived cast operation on /// the provided lvalue, which currently refers to the base object. static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E, LValue &Result) { SubobjectDesignator &D = Result.Designator; if (D.Invalid || !Result.checkNullPointer(Info, E, CSK_Derived)) return false; QualType TargetQT = E->getType(); if (const PointerType *PT = TargetQT->getAs()) TargetQT = PT->getPointeeType(); // Check this cast lands within the final derived-to-base subobject path. if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) { Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) << D.MostDerivedType << TargetQT; return false; } // Check the type of the final cast. We don't need to check the path, // since a cast can only be formed if the path is unique. unsigned NewEntriesSize = D.Entries.size() - E->path_size(); const CXXRecordDecl *TargetType = TargetQT->getAsCXXRecordDecl(); const CXXRecordDecl *FinalType; if (NewEntriesSize == D.MostDerivedPathLength) FinalType = D.MostDerivedType->getAsCXXRecordDecl(); else FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]); if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) { Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) << D.MostDerivedType << TargetQT; return false; } // Truncate the lvalue to the appropriate derived class. return CastToDerivedClass(Info, E, Result, TargetType, NewEntriesSize); } namespace { enum EvalStmtResult { /// Evaluation failed. ESR_Failed, /// Hit a 'return' statement. ESR_Returned, /// Evaluation succeeded. ESR_Succeeded, /// Hit a 'continue' statement. ESR_Continue, /// Hit a 'break' statement. ESR_Break, /// Still scanning for 'case' or 'default' statement. ESR_CaseNotFound }; } static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { // We don't need to evaluate the initializer for a static local. if (!VD->hasLocalStorage()) return true; LValue Result; Result.set(VD, Info.CurrentCall->Index); APValue &Val = Info.CurrentCall->createTemporary(VD, true); const Expr *InitE = VD->getInit(); if (!InitE) { Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized) << false << VD->getType(); Val = APValue(); return false; } if (InitE->isValueDependent()) return false; if (!EvaluateInPlace(Val, Info, Result, InitE)) { // Wipe out any partially-computed value, to allow tracking that this // evaluation failed. Val = APValue(); return false; } return true; } static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { bool OK = true; if (const VarDecl *VD = dyn_cast(D)) OK &= EvaluateVarDecl(Info, VD); if (const DecompositionDecl *DD = dyn_cast(D)) for (auto *BD : DD->bindings()) if (auto *VD = BD->getHoldingVar()) OK &= EvaluateDecl(Info, VD); return OK; } /// Evaluate a condition (either a variable declaration or an expression). static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, const Expr *Cond, bool &Result) { FullExpressionRAII Scope(Info); if (CondDecl && !EvaluateDecl(Info, CondDecl)) return false; return EvaluateAsBooleanCondition(Cond, Result, Info); } namespace { /// \brief A location where the result (returned value) of evaluating a /// statement should be stored. struct StmtResult { /// The APValue that should be filled in with the returned value. APValue &Value; /// The location containing the result, if any (used to support RVO). const LValue *Slot; }; } static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, const SwitchCase *SC = nullptr); /// Evaluate the body of a loop, and translate the result as appropriate. static EvalStmtResult EvaluateLoopBody(StmtResult &Result, EvalInfo &Info, const Stmt *Body, const SwitchCase *Case = nullptr) { BlockScopeRAII Scope(Info); switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) { case ESR_Break: return ESR_Succeeded; case ESR_Succeeded: case ESR_Continue: return ESR_Continue; case ESR_Failed: case ESR_Returned: case ESR_CaseNotFound: return ESR; } llvm_unreachable("Invalid EvalStmtResult!"); } /// Evaluate a switch statement. static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, const SwitchStmt *SS) { BlockScopeRAII Scope(Info); // Evaluate the switch condition. APSInt Value; { FullExpressionRAII Scope(Info); if (const Stmt *Init = SS->getInit()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); if (ESR != ESR_Succeeded) return ESR; } if (SS->getConditionVariable() && !EvaluateDecl(Info, SS->getConditionVariable())) return ESR_Failed; if (!EvaluateInteger(SS->getCond(), Value, Info)) return ESR_Failed; } // Find the switch case corresponding to the value of the condition. // FIXME: Cache this lookup. const SwitchCase *Found = nullptr; for (const SwitchCase *SC = SS->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { if (isa(SC)) { Found = SC; continue; } const CaseStmt *CS = cast(SC); APSInt LHS = CS->getLHS()->EvaluateKnownConstInt(Info.Ctx); APSInt RHS = CS->getRHS() ? CS->getRHS()->EvaluateKnownConstInt(Info.Ctx) : LHS; if (LHS <= Value && Value <= RHS) { Found = SC; break; } } if (!Found) return ESR_Succeeded; // Search the switch body for the switch case and evaluate it from there. switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, SS->getBody(), Found)) { case ESR_Break: return ESR_Succeeded; case ESR_Succeeded: case ESR_Continue: case ESR_Failed: case ESR_Returned: return ESR; case ESR_CaseNotFound: // This can only happen if the switch case is nested within a statement // expression. We have no intention of supporting that. Info.FFDiag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return ESR_Failed; } llvm_unreachable("Invalid EvalStmtResult!"); } // Evaluate a statement. static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, const SwitchCase *Case) { if (!Info.nextStep(S)) return ESR_Failed; // If we're hunting down a 'case' or 'default' label, recurse through // substatements until we hit the label. if (Case) { // FIXME: We don't start the lifetime of objects whose initialization we // jump over. However, such objects must be of class type with a trivial // default constructor that initialize all subobjects, so must be empty, // so this almost never matters. switch (S->getStmtClass()) { case Stmt::CompoundStmtClass: // FIXME: Precompute which substatement of a compound statement we // would jump to, and go straight there rather than performing a // linear scan each time. case Stmt::LabelStmtClass: case Stmt::AttributedStmtClass: case Stmt::DoStmtClass: break; case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: if (Case == S) Case = nullptr; break; case Stmt::IfStmtClass: { // FIXME: Precompute which side of an 'if' we would jump to, and go // straight there rather than scanning both sides. const IfStmt *IS = cast(S); // Wrap the evaluation in a block scope, in case it's a DeclStmt // preceded by our switch label. BlockScopeRAII Scope(Info); EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(), Case); if (ESR != ESR_CaseNotFound || !IS->getElse()) return ESR; return EvaluateStmt(Result, Info, IS->getElse(), Case); } case Stmt::WhileStmtClass: { EvalStmtResult ESR = EvaluateLoopBody(Result, Info, cast(S)->getBody(), Case); if (ESR != ESR_Continue) return ESR; break; } case Stmt::ForStmtClass: { const ForStmt *FS = cast(S); EvalStmtResult ESR = EvaluateLoopBody(Result, Info, FS->getBody(), Case); if (ESR != ESR_Continue) return ESR; if (FS->getInc()) { FullExpressionRAII IncScope(Info); if (!EvaluateIgnoredValue(Info, FS->getInc())) return ESR_Failed; } break; } case Stmt::DeclStmtClass: // FIXME: If the variable has initialization that can't be jumped over, // bail out of any immediately-surrounding compound-statement too. default: return ESR_CaseNotFound; } } switch (S->getStmtClass()) { default: if (const Expr *E = dyn_cast(S)) { // Don't bother evaluating beyond an expression-statement which couldn't // be evaluated. FullExpressionRAII Scope(Info); if (!EvaluateIgnoredValue(Info, E)) return ESR_Failed; return ESR_Succeeded; } Info.FFDiag(S->getLocStart()); return ESR_Failed; case Stmt::NullStmtClass: return ESR_Succeeded; case Stmt::DeclStmtClass: { const DeclStmt *DS = cast(S); for (const auto *DclIt : DS->decls()) { // Each declaration initialization is its own full-expression. // FIXME: This isn't quite right; if we're performing aggregate // initialization, each braced subexpression is its own full-expression. FullExpressionRAII Scope(Info); if (!EvaluateDecl(Info, DclIt) && !Info.noteFailure()) return ESR_Failed; } return ESR_Succeeded; } case Stmt::ReturnStmtClass: { const Expr *RetExpr = cast(S)->getRetValue(); FullExpressionRAII Scope(Info); if (RetExpr && !(Result.Slot ? EvaluateInPlace(Result.Value, Info, *Result.Slot, RetExpr) : Evaluate(Result.Value, Info, RetExpr))) return ESR_Failed; return ESR_Returned; } case Stmt::CompoundStmtClass: { BlockScopeRAII Scope(Info); const CompoundStmt *CS = cast(S); for (const auto *BI : CS->body()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, BI, Case); if (ESR == ESR_Succeeded) Case = nullptr; else if (ESR != ESR_CaseNotFound) return ESR; } return Case ? ESR_CaseNotFound : ESR_Succeeded; } case Stmt::IfStmtClass: { const IfStmt *IS = cast(S); // Evaluate the condition, as either a var decl or as an expression. BlockScopeRAII Scope(Info); if (const Stmt *Init = IS->getInit()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, Init); if (ESR != ESR_Succeeded) return ESR; } bool Cond; if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), Cond)) return ESR_Failed; if (const Stmt *SubStmt = Cond ? IS->getThen() : IS->getElse()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, SubStmt); if (ESR != ESR_Succeeded) return ESR; } return ESR_Succeeded; } case Stmt::WhileStmtClass: { const WhileStmt *WS = cast(S); while (true) { BlockScopeRAII Scope(Info); bool Continue; if (!EvaluateCond(Info, WS->getConditionVariable(), WS->getCond(), Continue)) return ESR_Failed; if (!Continue) break; EvalStmtResult ESR = EvaluateLoopBody(Result, Info, WS->getBody()); if (ESR != ESR_Continue) return ESR; } return ESR_Succeeded; } case Stmt::DoStmtClass: { const DoStmt *DS = cast(S); bool Continue; do { EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case); if (ESR != ESR_Continue) return ESR; Case = nullptr; FullExpressionRAII CondScope(Info); if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info)) return ESR_Failed; } while (Continue); return ESR_Succeeded; } case Stmt::ForStmtClass: { const ForStmt *FS = cast(S); BlockScopeRAII Scope(Info); if (FS->getInit()) { EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getInit()); if (ESR != ESR_Succeeded) return ESR; } while (true) { BlockScopeRAII Scope(Info); bool Continue = true; if (FS->getCond() && !EvaluateCond(Info, FS->getConditionVariable(), FS->getCond(), Continue)) return ESR_Failed; if (!Continue) break; EvalStmtResult ESR = EvaluateLoopBody(Result, Info, FS->getBody()); if (ESR != ESR_Continue) return ESR; if (FS->getInc()) { FullExpressionRAII IncScope(Info); if (!EvaluateIgnoredValue(Info, FS->getInc())) return ESR_Failed; } } return ESR_Succeeded; } case Stmt::CXXForRangeStmtClass: { const CXXForRangeStmt *FS = cast(S); BlockScopeRAII Scope(Info); // Initialize the __range variable. EvalStmtResult ESR = EvaluateStmt(Result, Info, FS->getRangeStmt()); if (ESR != ESR_Succeeded) return ESR; // Create the __begin and __end iterators. ESR = EvaluateStmt(Result, Info, FS->getBeginStmt()); if (ESR != ESR_Succeeded) return ESR; ESR = EvaluateStmt(Result, Info, FS->getEndStmt()); if (ESR != ESR_Succeeded) return ESR; while (true) { // Condition: __begin != __end. { bool Continue = true; FullExpressionRAII CondExpr(Info); if (!EvaluateAsBooleanCondition(FS->getCond(), Continue, Info)) return ESR_Failed; if (!Continue) break; } // User's variable declaration, initialized by *__begin. BlockScopeRAII InnerScope(Info); ESR = EvaluateStmt(Result, Info, FS->getLoopVarStmt()); if (ESR != ESR_Succeeded) return ESR; // Loop body. ESR = EvaluateLoopBody(Result, Info, FS->getBody()); if (ESR != ESR_Continue) return ESR; // Increment: ++__begin if (!EvaluateIgnoredValue(Info, FS->getInc())) return ESR_Failed; } return ESR_Succeeded; } case Stmt::SwitchStmtClass: return EvaluateSwitch(Result, Info, cast(S)); case Stmt::ContinueStmtClass: return ESR_Continue; case Stmt::BreakStmtClass: return ESR_Break; case Stmt::LabelStmtClass: return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); case Stmt::AttributedStmtClass: // As a general principle, C++11 attributes can be ignored without // any semantic impact. return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: return EvaluateStmt(Result, Info, cast(S)->getSubStmt(), Case); } } /// CheckTrivialDefaultConstructor - Check whether a constructor is a trivial /// default constructor. If so, we'll fold it whether or not it's marked as /// constexpr. If it is marked as constexpr, we will never implicitly define it, /// so we need special handling. static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, const CXXConstructorDecl *CD, bool IsValueInitialization) { if (!CD->isTrivial() || !CD->isDefaultConstructor()) return false; // Value-initialization does not call a trivial default constructor, so such a // call is a core constant expression whether or not the constructor is // constexpr. if (!CD->isConstexpr() && !IsValueInitialization) { if (Info.getLangOpts().CPlusPlus11) { // FIXME: If DiagDecl is an implicitly-declared special member function, // we should be much more explicit about why it's not constexpr. Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD; Info.Note(CD->getLocation(), diag::note_declared_at); } else { Info.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr); } } return true; } /// CheckConstexprFunction - Check that a function can be called in a constant /// expression. static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, const FunctionDecl *Declaration, const FunctionDecl *Definition, const Stmt *Body) { // Potential constant expressions can contain calls to declared, but not yet // defined, constexpr functions. if (Info.checkingPotentialConstantExpression() && !Definition && Declaration->isConstexpr()) return false; // Bail out with no diagnostic if the function declaration itself is invalid. // We will have produced a relevant diagnostic while parsing it. if (Declaration->isInvalidDecl()) return false; // Can we evaluate this function call? if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl() && Body) return true; if (Info.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; // If this function is not constexpr because it is an inherited // non-constexpr constructor, diagnose that directly. auto *CD = dyn_cast(DiagDecl); if (CD && CD->isInheritingConstructor()) { auto *Inherited = CD->getInheritedConstructor().getConstructor(); if (!Inherited->isConstexpr()) DiagDecl = CD = Inherited; } // FIXME: If DiagDecl is an implicitly-declared special member function // or an inheriting constructor, we should be much more explicit about why // it's not constexpr. if (CD && CD->isInheritingConstructor()) Info.FFDiag(CallLoc, diag::note_constexpr_invalid_inhctor, 1) << CD->getInheritedConstructor().getConstructor()->getParent(); else Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1) << DiagDecl->isConstexpr() << (bool)CD << DiagDecl; Info.Note(DiagDecl->getLocation(), diag::note_declared_at); } else { Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr); } return false; } /// Determine if a class has any fields that might need to be copied by a /// trivial copy or move operation. static bool hasFields(const CXXRecordDecl *RD) { if (!RD || RD->isEmpty()) return false; for (auto *FD : RD->fields()) { if (FD->isUnnamedBitfield()) continue; return true; } for (auto &Base : RD->bases()) if (hasFields(Base.getType()->getAsCXXRecordDecl())) return true; return false; } namespace { typedef SmallVector ArgVector; } /// EvaluateArgs - Evaluate the arguments to a function call. static bool EvaluateArgs(ArrayRef Args, ArgVector &ArgValues, EvalInfo &Info) { bool Success = true; for (ArrayRef::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. if (!Info.noteFailure()) return false; Success = false; } } return Success; } /// Evaluate a function call. static bool HandleFunctionCall(SourceLocation CallLoc, const FunctionDecl *Callee, const LValue *This, ArrayRef Args, const Stmt *Body, EvalInfo &Info, APValue &Result, const LValue *ResultSlot) { ArgVector ArgValues(Args.size()); if (!EvaluateArgs(Args, ArgValues, Info)) return false; if (!Info.CheckCallLimit(CallLoc)) return false; CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data()); // For a trivial copy or move assignment, perform an APValue copy. This is // essential for unions, where the operations performed by the assignment // operator cannot be represented as statements. // // Skip this for non-union classes with no fields; in that case, the defaulted // copy/move does not actually read the object. const CXXMethodDecl *MD = dyn_cast(Callee); if (MD && MD->isDefaulted() && (MD->getParent()->isUnion() || (MD->isTrivial() && hasFields(MD->getParent())))) { assert(This && (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())); LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); APValue RHSValue; if (!handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(), RHS, RHSValue)) return false; if (!handleAssignment(Info, Args[0], *This, MD->getThisType(Info.Ctx), RHSValue)) return false; This->moveInto(Result); return true; } StmtResult Ret = {Result, ResultSlot}; EvalStmtResult ESR = EvaluateStmt(Ret, Info, Body); if (ESR == ESR_Succeeded) { if (Callee->getReturnType()->isVoidType()) return true; Info.FFDiag(Callee->getLocEnd(), diag::note_constexpr_no_return); } return ESR == ESR_Returned; } /// Evaluate a constructor call. static bool HandleConstructorCall(const Expr *E, const LValue &This, APValue *ArgValues, const CXXConstructorDecl *Definition, EvalInfo &Info, APValue &Result) { SourceLocation CallLoc = E->getExprLoc(); if (!Info.CheckCallLimit(CallLoc)) return false; const CXXRecordDecl *RD = Definition->getParent(); if (RD->getNumVBases()) { Info.FFDiag(CallLoc, diag::note_constexpr_virtual_base) << RD; return false; } CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues); // FIXME: Creating an APValue just to hold a nonexistent return value is // wasteful. APValue RetVal; StmtResult Ret = {RetVal, nullptr}; // If it's a delegating constructor, delegate. if (Definition->isDelegatingConstructor()) { CXXConstructorDecl::init_const_iterator I = Definition->init_begin(); { FullExpressionRAII InitScope(Info); if (!EvaluateInPlace(Result, Info, This, (*I)->getInit())) return false; } return EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; } // For a trivial copy or move constructor, perform an APValue copy. This is // essential for unions (or classes with anonymous union members), where the // operations performed by the constructor cannot be represented by // ctor-initializers. // // Skip this for empty non-union classes; we should not perform an // lvalue-to-rvalue conversion on them because their copy constructor does not // actually read them. if (Definition->isDefaulted() && Definition->isCopyOrMoveConstructor() && (Definition->getParent()->isUnion() || (Definition->isTrivial() && hasFields(Definition->getParent())))) { LValue RHS; RHS.setFrom(Info.Ctx, ArgValues[0]); return handleLValueToRValueConversion( Info, E, Definition->getParamDecl(0)->getType().getNonReferenceType(), RHS, Result); } // Reserve space for the struct members. if (!RD->isUnion() && Result.isUninit()) Result = APValue(APValue::UninitStruct(), RD->getNumBases(), std::distance(RD->field_begin(), RD->field_end())); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); // A scope for temporaries lifetime-extended by reference members. BlockScopeRAII LifetimeExtendedScope(Info); bool Success = true; unsigned BasesSeen = 0; #ifndef NDEBUG CXXRecordDecl::base_class_const_iterator BaseIt = RD->bases_begin(); #endif for (const auto *I : Definition->inits()) { LValue Subobject = This; APValue *Value = &Result; // Determine the subobject to initialize. FieldDecl *FD = nullptr; if (I->isBaseInitializer()) { QualType BaseType(I->getBaseClass(), 0); #ifndef NDEBUG // Non-virtual base classes are initialized in the order in the class // definition. We have already checked for virtual base classes. assert(!BaseIt->isVirtual() && "virtual base for literal type"); assert(Info.Ctx.hasSameType(BaseIt->getType(), BaseType) && "base class initializers not in expected order"); ++BaseIt; #endif if (!HandleLValueDirectBase(Info, I->getInit(), Subobject, RD, BaseType->getAsCXXRecordDecl(), &Layout)) return false; Value = &Result.getStructBase(BasesSeen++); } else if ((FD = I->getMember())) { if (!HandleLValueMember(Info, I->getInit(), Subobject, FD, &Layout)) return false; if (RD->isUnion()) { Result = APValue(FD); Value = &Result.getUnionValue(); } else { Value = &Result.getStructField(FD->getFieldIndex()); } } else if (IndirectFieldDecl *IFD = I->getIndirectMember()) { // Walk the indirect field decl's chain to find the object to initialize, // and make sure we've initialized every step along it. for (auto *C : IFD->chain()) { FD = cast(C); CXXRecordDecl *CD = cast(FD->getParent()); // Switch the union field if it differs. This happens if we had // preceding zero-initialization, and we're now initializing a union // subobject other than the first. // FIXME: In this case, the values of the other subobjects are // specified, since zero-initialization sets all padding bits to zero. if (Value->isUninit() || (Value->isUnion() && Value->getUnionField() != FD)) { if (CD->isUnion()) *Value = APValue(FD); else *Value = APValue(APValue::UninitStruct(), CD->getNumBases(), std::distance(CD->field_begin(), CD->field_end())); } if (!HandleLValueMember(Info, I->getInit(), Subobject, FD)) return false; if (CD->isUnion()) Value = &Value->getUnionValue(); else Value = &Value->getStructField(FD->getFieldIndex()); } } else { llvm_unreachable("unknown base initializer kind"); } FullExpressionRAII InitScope(Info); if (!EvaluateInPlace(*Value, Info, Subobject, I->getInit()) || (FD && FD->isBitField() && !truncateBitfieldValue(Info, I->getInit(), *Value, FD))) { // If we're checking for a potential constant expression, evaluate all // initializers even if some of them fail. if (!Info.noteFailure()) return false; Success = false; } } return Success && EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed; } static bool HandleConstructorCall(const Expr *E, const LValue &This, ArrayRef Args, const CXXConstructorDecl *Definition, EvalInfo &Info, APValue &Result) { ArgVector ArgValues(Args.size()); if (!EvaluateArgs(Args, ArgValues, Info)) return false; return HandleConstructorCall(E, This, ArgValues.data(), Definition, Info, Result); } //===----------------------------------------------------------------------===// // Generic Evaluation //===----------------------------------------------------------------------===// namespace { template class ExprEvaluatorBase : public ConstStmtVisitor { private: Derived &getDerived() { return static_cast(*this); } bool DerivedSuccess(const APValue &V, const Expr *E) { return getDerived().Success(V, E); } bool DerivedZeroInitialization(const Expr *E) { return getDerived().ZeroInitialization(E); } // Check whether a conditional operator with a non-constant condition is a // potential constant expression. If neither arm is a potential constant // expression, then the conditional operator is not either. template void CheckPotentialConstantConditional(const ConditionalOperator *E) { assert(Info.checkingPotentialConstantExpression()); // Speculatively evaluate both arms. SmallVector Diag; { SpeculativeEvaluationRAII Speculate(Info, &Diag); StmtVisitorTy::Visit(E->getFalseExpr()); if (Diag.empty()) return; } { SpeculativeEvaluationRAII Speculate(Info, &Diag); Diag.clear(); StmtVisitorTy::Visit(E->getTrueExpr()); if (Diag.empty()) return; } Error(E, diag::note_constexpr_conditional_never_const); } template bool HandleConditionalOperator(const ConditionalOperator *E) { bool BoolResult; if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) { if (Info.checkingPotentialConstantExpression() && Info.noteFailure()) CheckPotentialConstantConditional(E); return false; } Expr *EvalExpr = BoolResult ? E->getTrueExpr() : E->getFalseExpr(); return StmtVisitorTy::Visit(EvalExpr); } protected: EvalInfo &Info; typedef ConstStmtVisitor StmtVisitorTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { return Info.CCEDiag(E, D); } bool ZeroInitialization(const Expr *E) { return Error(E); } public: ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {} EvalInfo &getEvalInfo() { return Info; } /// Report an evaluation error. This should only be called when an error is /// first discovered. When propagating an error, just return false. bool Error(const Expr *E, diag::kind D) { Info.FFDiag(E, D); return false; } bool Error(const Expr *E) { return Error(E, diag::note_invalid_subexpr_in_const_expr); } bool VisitStmt(const Stmt *) { llvm_unreachable("Expression evaluator should not be called on stmts"); } bool VisitExpr(const Expr *E) { return Error(E); } bool VisitParenExpr(const ParenExpr *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitUnaryExtension(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitUnaryPlus(const UnaryOperator *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitChooseExpr(const ChooseExpr *E) { return StmtVisitorTy::Visit(E->getChosenSubExpr()); } bool VisitGenericSelectionExpr(const GenericSelectionExpr *E) { return StmtVisitorTy::Visit(E->getResultExpr()); } bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E) { return StmtVisitorTy::Visit(E->getReplacement()); } bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { return StmtVisitorTy::Visit(E->getExpr()); } bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { // The initializer may not have been parsed yet, or might be erroneous. if (!E->getExpr()) return Error(E); return StmtVisitorTy::Visit(E->getExpr()); } // We cannot create any objects for which cleanups are required, so there is // nothing to do here; all cleanups must come from unevaluated subexpressions. bool VisitExprWithCleanups(const ExprWithCleanups *E) { return StmtVisitorTy::Visit(E->getSubExpr()); } bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 0; return static_cast(this)->VisitCastExpr(E); } bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) { CCEDiag(E, diag::note_constexpr_invalid_cast) << 1; return static_cast(this)->VisitCastExpr(E); } bool VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: return Error(E); case BO_Comma: VisitIgnoredValue(E->getLHS()); return StmtVisitorTy::Visit(E->getRHS()); case BO_PtrMemD: case BO_PtrMemI: { LValue Obj; if (!HandleMemberPointerAccess(Info, E, Obj)) return false; APValue Result; if (!handleLValueToRValueConversion(Info, E, E->getType(), Obj, Result)) return false; return DerivedSuccess(Result, E); } } } bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) { // Evaluate and cache the common expression. We treat it as a temporary, // even though it's not quite the same thing. if (!Evaluate(Info.CurrentCall->createTemporary(E->getOpaqueValue(), false), Info, E->getCommon())) return false; return HandleConditionalOperator(E); } bool VisitConditionalOperator(const ConditionalOperator *E) { bool IsBcpCall = false; // If the condition (ignoring parens) is a __builtin_constant_p call, // the result is a constant expression if it can be folded without // side-effects. This is an important GNU extension. See GCC PR38377 // for discussion. if (const CallExpr *CallCE = dyn_cast(E->getCond()->IgnoreParenCasts())) if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) IsBcpCall = true; // Always assume __builtin_constant_p(...) ? ... : ... is a potential // constant expression; we can't check whether it's potentially foldable. if (Info.checkingPotentialConstantExpression() && IsBcpCall) return false; FoldConstant Fold(Info, IsBcpCall); if (!HandleConditionalOperator(E)) { Fold.keepDiagnostics(); return false; } return true; } bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) { if (APValue *Value = Info.CurrentCall->getTemporary(E)) return DerivedSuccess(*Value, E); const Expr *Source = E->getSourceExpr(); if (!Source) return Error(E); if (Source == E) { // sanity checking. assert(0 && "OpaqueValueExpr recursively refers to itself"); return Error(E); } return StmtVisitorTy::Visit(Source); } bool VisitCallExpr(const CallExpr *E) { APValue Result; if (!handleCallExpr(E, Result, nullptr)) return false; return DerivedSuccess(Result, E); } bool handleCallExpr(const CallExpr *E, APValue &Result, const LValue *ResultSlot) { const Expr *Callee = E->getCallee()->IgnoreParens(); QualType CalleeType = Callee->getType(); const FunctionDecl *FD = nullptr; LValue *This = nullptr, ThisVal; auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { const ValueDecl *Member = nullptr; if (const MemberExpr *ME = dyn_cast(Callee)) { // Explicit bound member calls, such as x.f() or p->g(); if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal)) return false; Member = ME->getMemberDecl(); This = &ThisVal; HasQualifier = ME->hasQualifier(); } else if (const BinaryOperator *BE = dyn_cast(Callee)) { // Indirect bound member calls ('.*' or '->*'). Member = HandleMemberPointerAccess(Info, BE, ThisVal, false); if (!Member) return false; This = &ThisVal; } else return Error(Callee); FD = dyn_cast(Member); if (!FD) return Error(Callee); } else if (CalleeType->isFunctionPointerType()) { LValue Call; if (!EvaluatePointer(Callee, Call, Info)) return false; if (!Call.getLValueOffset().isZero()) return Error(Callee); FD = dyn_cast_or_null( Call.getLValueBase().dyn_cast()); if (!FD) return Error(Callee); // Don't call function pointers which have been cast to some other type. // Per DR (no number yet), the caller and callee can differ in noexcept. if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec( CalleeType->getPointeeType(), FD->getType())) { return Error(E); } // Overloaded operator calls to member functions are represented as normal // calls with '*this' as the first argument. const CXXMethodDecl *MD = dyn_cast(FD); if (MD && !MD->isStatic()) { // FIXME: When selecting an implicit conversion for an overloaded // operator delete, we sometimes try to evaluate calls to conversion // operators without a 'this' parameter! if (Args.empty()) return Error(E); if (!EvaluateObjectArgument(Info, Args[0], ThisVal)) return false; This = &ThisVal; Args = Args.slice(1); } else if (MD && MD->isLambdaStaticInvoker()) { // Map the static invoker for the lambda back to the call operator. // Conveniently, we don't have to slice out the 'this' argument (as is // being done for the non-static case), since a static member function // doesn't have an implicit argument passed in. const CXXRecordDecl *ClosureClass = MD->getParent(); assert( ClosureClass->captures_begin() == ClosureClass->captures_end() && "Number of captures must be zero for conversion to function-ptr"); const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator(); // Set 'FD', the function that will be called below, to the call // operator. If the closure object represents a generic lambda, find // the corresponding specialization of the call operator. if (ClosureClass->isGenericLambda()) { assert(MD->isFunctionTemplateSpecialization() && "A generic lambda's static-invoker function must be a " "template specialization"); const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); FunctionTemplateDecl *CallOpTemplate = LambdaCallOp->getDescribedFunctionTemplate(); void *InsertPos = nullptr; FunctionDecl *CorrespondingCallOpSpecialization = CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); assert(CorrespondingCallOpSpecialization && "We must always have a function call operator specialization " "that corresponds to our static invoker specialization"); FD = cast(CorrespondingCallOpSpecialization); } else FD = LambdaCallOp; } } else return Error(E); if (This && !This->checkSubobject(Info, E, CSK_This)) return false; // DR1358 allows virtual constexpr functions in some cases. Don't allow // calls to such functions in constant expressions. if (This && !HasQualifier && isa(FD) && cast(FD)->isVirtual()) return Error(E, diag::note_constexpr_virtual_call); const FunctionDecl *Definition = nullptr; Stmt *Body = FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) || !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info, Result, ResultSlot)) return false; return true; } bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { return StmtVisitorTy::Visit(E->getInitializer()); } bool VisitInitListExpr(const InitListExpr *E) { if (E->getNumInits() == 0) return DerivedZeroInitialization(E); if (E->getNumInits() == 1) return StmtVisitorTy::Visit(E->getInit(0)); return Error(E); } bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return DerivedZeroInitialization(E); } bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) { return DerivedZeroInitialization(E); } bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { return DerivedZeroInitialization(E); } /// A member expression where the object is a prvalue is itself a prvalue. bool VisitMemberExpr(const MemberExpr *E) { assert(!E->isArrow() && "missing call to bound member function?"); APValue Val; if (!Evaluate(Val, Info, E->getBase())) return false; QualType BaseTy = E->getBase()->getType(); const FieldDecl *FD = dyn_cast(E->getMemberDecl()); if (!FD) return Error(E); assert(!FD->getType()->isReferenceType() && "prvalue reference?"); assert(BaseTy->castAs()->getDecl()->getCanonicalDecl() == FD->getParent()->getCanonicalDecl() && "record / field mismatch"); CompleteObject Obj(&Val, BaseTy); SubobjectDesignator Designator(BaseTy); Designator.addDeclUnchecked(FD); APValue Result; return extractSubobject(Info, E, Obj, Designator, Result) && DerivedSuccess(Result, E); } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: break; case CK_AtomicToNonAtomic: { APValue AtomicVal; if (!EvaluateAtomic(E->getSubExpr(), AtomicVal, Info)) return false; return DerivedSuccess(AtomicVal, E); } case CK_NoOp: case CK_UserDefinedConversion: return StmtVisitorTy::Visit(E->getSubExpr()); case CK_LValueToRValue: { LValue LVal; if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) return false; APValue RVal; // Note, we use the subexpression's type in order to retain cv-qualifiers. if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), LVal, RVal)) return false; return DerivedSuccess(RVal, E); } } return Error(E); } bool VisitUnaryPostInc(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } bool VisitUnaryPostDec(const UnaryOperator *UO) { return VisitUnaryPostIncDec(UO); } bool VisitUnaryPostIncDec(const UnaryOperator *UO) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(UO); LValue LVal; if (!EvaluateLValue(UO->getSubExpr(), LVal, Info)) return false; APValue RVal; if (!handleIncDec(this->Info, UO, LVal, UO->getSubExpr()->getType(), UO->isIncrementOp(), &RVal)) return false; return DerivedSuccess(RVal, UO); } bool VisitStmtExpr(const StmtExpr *E) { // We will have checked the full-expressions inside the statement expression // when they were completed, and don't need to check them again now. if (Info.checkingForOverflow()) return Error(E); BlockScopeRAII Scope(Info); const CompoundStmt *CS = E->getSubStmt(); if (CS->body_empty()) return true; for (CompoundStmt::const_body_iterator BI = CS->body_begin(), BE = CS->body_end(); /**/; ++BI) { if (BI + 1 == BE) { const Expr *FinalExpr = dyn_cast(*BI); if (!FinalExpr) { Info.FFDiag((*BI)->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return false; } return this->Visit(FinalExpr); } APValue ReturnValue; StmtResult Result = { ReturnValue, nullptr }; EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI); if (ESR != ESR_Succeeded) { // FIXME: If the statement-expression terminated due to 'return', // 'break', or 'continue', it would be nice to propagate that to // the outer statement evaluation rather than bailing out. if (ESR != ESR_Failed) Info.FFDiag((*BI)->getLocStart(), diag::note_constexpr_stmt_expr_unsupported); return false; } } llvm_unreachable("Return from function from the loop above."); } /// Visit a value which is evaluated, but whose value is ignored. void VisitIgnoredValue(const Expr *E) { EvaluateIgnoredValue(Info, E); } /// Potentially visit a MemberExpr's base expression. void VisitIgnoredBaseExpression(const Expr *E) { // While MSVC doesn't evaluate the base expression, it does diagnose the // presence of side-effecting behavior. if (Info.getLangOpts().MSVCCompat && !E->HasSideEffects(Info.Ctx)) return; VisitIgnoredValue(E); } }; } //===----------------------------------------------------------------------===// // Common base class for lvalue and temporary evaluation. //===----------------------------------------------------------------------===// namespace { template class LValueExprEvaluatorBase : public ExprEvaluatorBase { protected: LValue &Result; + bool InvalidBaseOK; typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy; typedef ExprEvaluatorBase ExprEvaluatorBaseTy; bool Success(APValue::LValueBase B) { Result.set(B); return true; } + bool evaluatePointer(const Expr *E, LValue &Result) { + return EvaluatePointer(E, Result, this->Info, InvalidBaseOK); + } + public: - LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result) : - ExprEvaluatorBaseTy(Info), Result(Result) {} + LValueExprEvaluatorBase(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) + : ExprEvaluatorBaseTy(Info), Result(Result), + InvalidBaseOK(InvalidBaseOK) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(this->Info.Ctx, V); return true; } bool VisitMemberExpr(const MemberExpr *E) { // Handle non-static data members. QualType BaseTy; bool EvalOK; if (E->isArrow()) { - EvalOK = EvaluatePointer(E->getBase(), Result, this->Info); + EvalOK = evaluatePointer(E->getBase(), Result); BaseTy = E->getBase()->getType()->castAs()->getPointeeType(); } else if (E->getBase()->isRValue()) { assert(E->getBase()->getType()->isRecordType()); EvalOK = EvaluateTemporary(E->getBase(), Result, this->Info); BaseTy = E->getBase()->getType(); } else { EvalOK = this->Visit(E->getBase()); BaseTy = E->getBase()->getType(); } if (!EvalOK) { - if (!this->Info.allowInvalidBaseExpr()) + if (!InvalidBaseOK) return false; Result.setInvalid(E); return true; } const ValueDecl *MD = E->getMemberDecl(); if (const FieldDecl *FD = dyn_cast(E->getMemberDecl())) { assert(BaseTy->getAs()->getDecl()->getCanonicalDecl() == FD->getParent()->getCanonicalDecl() && "record / field mismatch"); (void)BaseTy; if (!HandleLValueMember(this->Info, E, Result, FD)) return false; } else if (const IndirectFieldDecl *IFD = dyn_cast(MD)) { if (!HandleLValueIndirectMember(this->Info, E, Result, IFD)) return false; } else return this->Error(E); if (MD->getType()->isReferenceType()) { APValue RefValue; if (!handleLValueToRValueConversion(this->Info, E, MD->getType(), Result, RefValue)) return false; return Success(RefValue, E); } return true; } bool VisitBinaryOperator(const BinaryOperator *E) { switch (E->getOpcode()) { default: return ExprEvaluatorBaseTy::VisitBinaryOperator(E); case BO_PtrMemD: case BO_PtrMemI: return HandleMemberPointerAccess(this->Info, E, Result); } } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_DerivedToBase: case CK_UncheckedDerivedToBase: if (!this->Visit(E->getSubExpr())) return false; // Now figure out the necessary offset to add to the base LV to get from // the derived class to the base class. return HandleLValueBasePath(this->Info, E, E->getSubExpr()->getType(), Result); } } }; } //===----------------------------------------------------------------------===// // LValue Evaluation // // This is used for evaluating lvalues (in C and C++), xvalues (in C++11), // function designators (in C), decl references to void objects (in C), and // temporaries (if building with -Wno-address-of-temporary). // // LValue evaluation produces values comprising a base expression of one of the // following types: // - Declarations // * VarDecl // * FunctionDecl // - Literals // * CompoundLiteralExpr in C (and in global scope in C++) // * StringLiteral // * CXXTypeidExpr // * PredefinedExpr // * ObjCStringLiteralExpr // * ObjCEncodeExpr // * AddrLabelExpr // * BlockExpr // * CallExpr for a MakeStringConstant builtin // - Locals and temporaries // * MaterializeTemporaryExpr // * Any Expr, with a CallIndex indicating the function in which the temporary // was evaluated, for cases where the MaterializeTemporaryExpr is missing // from the AST (FIXME). // * A MaterializeTemporaryExpr that has static storage duration, with no // CallIndex, for a lifetime-extended temporary. // plus an offset in bytes. //===----------------------------------------------------------------------===// namespace { class LValueExprEvaluator : public LValueExprEvaluatorBase { public: - LValueExprEvaluator(EvalInfo &Info, LValue &Result) : - LValueExprEvaluatorBaseTy(Info, Result) {} + LValueExprEvaluator(EvalInfo &Info, LValue &Result, bool InvalidBaseOK) : + LValueExprEvaluatorBaseTy(Info, Result, InvalidBaseOK) {} bool VisitVarDecl(const Expr *E, const VarDecl *VD); bool VisitUnaryPreIncDec(const UnaryOperator *UO); bool VisitDeclRefExpr(const DeclRefExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E) { return Success(E); } bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); bool VisitMemberExpr(const MemberExpr *E); bool VisitStringLiteral(const StringLiteral *E) { return Success(E); } bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return Success(E); } bool VisitCXXTypeidExpr(const CXXTypeidExpr *E); bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); bool VisitUnaryDeref(const UnaryOperator *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); bool VisitUnaryPreInc(const UnaryOperator *UO) { return VisitUnaryPreIncDec(UO); } bool VisitUnaryPreDec(const UnaryOperator *UO) { return VisitUnaryPreIncDec(UO); } bool VisitBinAssign(const BinaryOperator *BO); bool VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return LValueExprEvaluatorBaseTy::VisitCastExpr(E); case CK_LValueBitCast: this->CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; if (!Visit(E->getSubExpr())) return false; Result.Designator.setInvalid(); return true; case CK_BaseToDerived: if (!Visit(E->getSubExpr())) return false; return HandleBaseToDerivedCast(Info, E, Result); } } }; } // end anonymous namespace /// Evaluate an expression as an lvalue. This can be legitimately called on /// expressions which are not glvalues, in three cases: /// * function designators in C, and /// * "extern void" objects /// * @selector() expressions in Objective-C -static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info) { +static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info, + bool InvalidBaseOK) { assert(E->isGLValue() || E->getType()->isFunctionType() || E->getType()->isVoidType() || isa(E)); - return LValueExprEvaluator(Info, Result).Visit(E); + return LValueExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); } bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { if (const FunctionDecl *FD = dyn_cast(E->getDecl())) return Success(FD); if (const VarDecl *VD = dyn_cast(E->getDecl())) return VisitVarDecl(E, VD); if (const BindingDecl *BD = dyn_cast(E->getDecl())) return Visit(BD->getBinding()); return Error(E); } bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { CallStackFrame *Frame = nullptr; if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) { // Only if a local variable was declared in the function currently being // evaluated, do we expect to be able to find its value in the current // frame. (Otherwise it was likely declared in an enclosing context and // could either have a valid evaluatable value (for e.g. a constexpr // variable) or be ill-formed (and trigger an appropriate evaluation // diagnostic)). if (Info.CurrentCall->Callee && Info.CurrentCall->Callee->Equals(VD->getDeclContext())) { Frame = Info.CurrentCall; } } if (!VD->getType()->isReferenceType()) { if (Frame) { Result.set(VD, Frame->Index); return true; } return Success(VD); } APValue *V; if (!evaluateVarDeclInit(Info, E, VD, Frame, V)) return false; if (V->isUninit()) { if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_constexpr_use_uninit_reference); return false; } return Success(*V, E); } bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *E) { // Walk through the expression to find the materialized temporary itself. SmallVector CommaLHSs; SmallVector Adjustments; const Expr *Inner = E->GetTemporaryExpr()-> skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); // If we passed any comma operators, evaluate their LHSs. for (unsigned I = 0, N = CommaLHSs.size(); I != N; ++I) if (!EvaluateIgnoredValue(Info, CommaLHSs[I])) return false; // A materialized temporary with static storage duration can appear within the // result of a constant expression evaluation, so we need to preserve its // value for use outside this evaluation. APValue *Value; if (E->getStorageDuration() == SD_Static) { Value = Info.Ctx.getMaterializedTemporaryValue(E, true); *Value = APValue(); Result.set(E); } else { Value = &Info.CurrentCall-> createTemporary(E, E->getStorageDuration() == SD_Automatic); Result.set(E, Info.CurrentCall->Index); } QualType Type = Inner->getType(); // Materialize the temporary itself. if (!EvaluateInPlace(*Value, Info, Result, Inner) || (E->getStorageDuration() == SD_Static && !CheckConstantExpression(Info, E->getExprLoc(), Type, *Value))) { *Value = APValue(); return false; } // Adjust our lvalue to refer to the desired subobject. for (unsigned I = Adjustments.size(); I != 0; /**/) { --I; switch (Adjustments[I].Kind) { case SubobjectAdjustment::DerivedToBaseAdjustment: if (!HandleLValueBasePath(Info, Adjustments[I].DerivedToBase.BasePath, Type, Result)) return false; Type = Adjustments[I].DerivedToBase.BasePath->getType(); break; case SubobjectAdjustment::FieldAdjustment: if (!HandleLValueMember(Info, E, Result, Adjustments[I].Field)) return false; Type = Adjustments[I].Field->getType(); break; case SubobjectAdjustment::MemberPointerAdjustment: if (!HandleMemberPointerAccess(this->Info, Type, Result, Adjustments[I].Ptr.RHS)) return false; Type = Adjustments[I].Ptr.MPT->getPointeeType(); break; } } return true; } bool LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) && "lvalue compound literal in c++?"); // Defer visiting the literal until the lvalue-to-rvalue conversion. We can // only see this when folding in C, so there's no standard to follow here. return Success(E); } bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { if (!E->isPotentiallyEvaluated()) return Success(E); Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic) << E->getExprOperand()->getType() << E->getExprOperand()->getSourceRange(); return false; } bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { return Success(E); } bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { // Handle static data members. if (const VarDecl *VD = dyn_cast(E->getMemberDecl())) { VisitIgnoredBaseExpression(E->getBase()); return VisitVarDecl(E, VD); } // Handle static member functions. if (const CXXMethodDecl *MD = dyn_cast(E->getMemberDecl())) { if (MD->isStatic()) { VisitIgnoredBaseExpression(E->getBase()); return Success(MD); } } // Handle non-static data members. return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); } bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { // FIXME: Deal with vectors as array subscript bases. if (E->getBase()->getType()->isVectorType()) return Error(E); - if (!EvaluatePointer(E->getBase(), Result, Info)) + if (!evaluatePointer(E->getBase(), Result)) return false; APSInt Index; if (!EvaluateInteger(E->getIdx(), Index, Info)) return false; return HandleLValueArrayAdjustment(Info, E, Result, E->getType(), getExtValue(Index)); } bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) { - return EvaluatePointer(E->getSubExpr(), Result, Info); + return evaluatePointer(E->getSubExpr(), Result); } bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (!Visit(E->getSubExpr())) return false; // __real is a no-op on scalar lvalues. if (E->getSubExpr()->getType()->isAnyComplexType()) HandleLValueComplexElement(Info, E, Result, E->getType(), false); return true; } bool LValueExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { assert(E->getSubExpr()->getType()->isAnyComplexType() && "lvalue __imag__ on scalar?"); if (!Visit(E->getSubExpr())) return false; HandleLValueComplexElement(Info, E, Result, E->getType(), true); return true; } bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(UO); if (!this->Visit(UO->getSubExpr())) return false; return handleIncDec( this->Info, UO, Result, UO->getSubExpr()->getType(), UO->isIncrementOp(), nullptr); } bool LValueExprEvaluator::VisitCompoundAssignOperator( const CompoundAssignOperator *CAO) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(CAO); APValue RHS; // The overall lvalue result is the result of evaluating the LHS. if (!this->Visit(CAO->getLHS())) { if (Info.noteFailure()) Evaluate(RHS, this->Info, CAO->getRHS()); return false; } if (!Evaluate(RHS, this->Info, CAO->getRHS())) return false; return handleCompoundAssignment( this->Info, CAO, Result, CAO->getLHS()->getType(), CAO->getComputationLHSType(), CAO->getOpForCompoundAssignment(CAO->getOpcode()), RHS); } bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) { if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure()) return Error(E); APValue NewVal; if (!this->Visit(E->getLHS())) { if (Info.noteFailure()) Evaluate(NewVal, this->Info, E->getRHS()); return false; } if (!Evaluate(NewVal, this->Info, E->getRHS())) return false; return handleAssignment(this->Info, E, Result, E->getLHS()->getType(), NewVal); } //===----------------------------------------------------------------------===// // Pointer Evaluation //===----------------------------------------------------------------------===// /// \brief Attempts to compute the number of bytes available at the pointer /// returned by a function with the alloc_size attribute. Returns true if we /// were successful. Places an unsigned number into `Result`. /// /// This expects the given CallExpr to be a call to a function with an /// alloc_size attribute. static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, const CallExpr *Call, llvm::APInt &Result) { const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call); // alloc_size args are 1-indexed, 0 means not present. assert(AllocSize && AllocSize->getElemSizeParam() != 0); unsigned SizeArgNo = AllocSize->getElemSizeParam() - 1; unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType()); if (Call->getNumArgs() <= SizeArgNo) return false; auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects)) return false; if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) return false; Into = Into.zextOrSelf(BitsInSizeT); return true; }; APSInt SizeOfElem; if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem)) return false; if (!AllocSize->getNumElemsParam()) { Result = std::move(SizeOfElem); return true; } APSInt NumberOfElems; // Argument numbers start at 1 unsigned NumArgNo = AllocSize->getNumElemsParam() - 1; if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems)) return false; bool Overflow; llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow); if (Overflow) return false; Result = std::move(BytesAvailable); return true; } /// \brief Convenience function. LVal's base must be a call to an alloc_size /// function. static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, const LValue &LVal, llvm::APInt &Result) { assert(isBaseAnAllocSizeCall(LVal.getLValueBase()) && "Can't get the size of a non alloc_size function"); const auto *Base = LVal.getLValueBase().get(); const CallExpr *CE = tryUnwrapAllocSizeCall(Base); return getBytesReturnedByAllocSizeCall(Ctx, CE, Result); } /// \brief Attempts to evaluate the given LValueBase as the result of a call to /// a function with the alloc_size attribute. If it was possible to do so, this /// function will return true, make Result's Base point to said function call, /// and mark Result's Base as invalid. static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base, LValue &Result) { - if (!Info.allowInvalidBaseExpr() || Base.isNull()) + if (Base.isNull()) return false; // Because we do no form of static analysis, we only support const variables. // // Additionally, we can't support parameters, nor can we support static // variables (in the latter case, use-before-assign isn't UB; in the former, // we have no clue what they'll be assigned to). const auto *VD = dyn_cast_or_null(Base.dyn_cast()); if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualified()) return false; const Expr *Init = VD->getAnyInitializer(); if (!Init) return false; const Expr *E = Init->IgnoreParens(); if (!tryUnwrapAllocSizeCall(E)) return false; // Store E instead of E unwrapped so that the type of the LValue's base is // what the user wanted. Result.setInvalid(E); QualType Pointee = E->getType()->castAs()->getPointeeType(); Result.addUnsizedArray(Info, Pointee); return true; } namespace { class PointerExprEvaluator : public ExprEvaluatorBase { LValue &Result; + bool InvalidBaseOK; bool Success(const Expr *E) { Result.set(E); return true; } + bool evaluateLValue(const Expr *E, LValue &Result) { + return EvaluateLValue(E, Result, Info, InvalidBaseOK); + } + + bool evaluatePointer(const Expr *E, LValue &Result) { + return EvaluatePointer(E, Result, Info, InvalidBaseOK); + } + bool visitNonBuiltinCallExpr(const CallExpr *E); public: - PointerExprEvaluator(EvalInfo &info, LValue &Result) - : ExprEvaluatorBaseTy(info), Result(Result) {} + PointerExprEvaluator(EvalInfo &info, LValue &Result, bool InvalidBaseOK) + : ExprEvaluatorBaseTy(info), Result(Result), + InvalidBaseOK(InvalidBaseOK) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(Info.Ctx, V); return true; } bool ZeroInitialization(const Expr *E) { auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType()); Result.set((Expr*)nullptr, 0, false, true, Offset); return true; } bool VisitBinaryOperator(const BinaryOperator *E); bool VisitCastExpr(const CastExpr* E); bool VisitUnaryAddrOf(const UnaryOperator *E); bool VisitObjCStringLiteral(const ObjCStringLiteral *E) { return Success(E); } bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { return Success(E); } bool VisitAddrLabelExpr(const AddrLabelExpr *E) { return Success(E); } bool VisitCallExpr(const CallExpr *E); bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBlockExpr(const BlockExpr *E) { if (!E->getBlockDecl()->hasCaptures()) return Success(E); return Error(E); } bool VisitCXXThisExpr(const CXXThisExpr *E) { // Can't look at 'this' when checking a potential constant expression. if (Info.checkingPotentialConstantExpression()) return false; if (!Info.CurrentCall->This) { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); else Info.FFDiag(E); return false; } Result = *Info.CurrentCall->This; return true; } // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace -static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) { +static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info, + bool InvalidBaseOK) { assert(E->isRValue() && E->getType()->hasPointerRepresentation()); - return PointerExprEvaluator(Info, Result).Visit(E); + return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E); } bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->getOpcode() != BO_Add && E->getOpcode() != BO_Sub) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); const Expr *PExp = E->getLHS(); const Expr *IExp = E->getRHS(); if (IExp->getType()->isPointerType()) std::swap(PExp, IExp); - bool EvalPtrOK = EvaluatePointer(PExp, Result, Info); + bool EvalPtrOK = evaluatePointer(PExp, Result); if (!EvalPtrOK && !Info.noteFailure()) return false; llvm::APSInt Offset; if (!EvaluateInteger(IExp, Offset, Info) || !EvalPtrOK) return false; int64_t AdditionalOffset = getExtValue(Offset); if (E->getOpcode() == BO_Sub) AdditionalOffset = -AdditionalOffset; QualType Pointee = PExp->getType()->castAs()->getPointeeType(); return HandleLValueArrayAdjustment(Info, E, Result, Pointee, AdditionalOffset); } bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { - return EvaluateLValue(E->getSubExpr(), Result, Info); + return evaluateLValue(E->getSubExpr(), Result); } bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { const Expr* SubExpr = E->getSubExpr(); switch (E->getCastKind()) { default: break; case CK_BitCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_AddressSpaceConversion: if (!Visit(SubExpr)) return false; // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) CCEDiag(E, diag::note_constexpr_invalid_cast) << 3 << SubExpr->getType(); else CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; } if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) ZeroInitialization(E); return true; case CK_DerivedToBase: case CK_UncheckedDerivedToBase: - if (!EvaluatePointer(E->getSubExpr(), Result, Info)) + if (!evaluatePointer(E->getSubExpr(), Result)) return false; if (!Result.Base && Result.Offset.isZero()) return true; // Now figure out the necessary offset to add to the base LV to get from // the derived class to the base class. return HandleLValueBasePath(Info, E, E->getSubExpr()->getType()-> castAs()->getPointeeType(), Result); case CK_BaseToDerived: if (!Visit(E->getSubExpr())) return false; if (!Result.Base && Result.Offset.isZero()) return true; return HandleBaseToDerivedCast(Info, E, Result); case CK_NullToPointer: VisitIgnoredValue(E->getSubExpr()); return ZeroInitialization(E); case CK_IntegralToPointer: { CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) break; if (Value.isInt()) { unsigned Size = Info.Ctx.getTypeSize(E->getType()); uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue(); Result.Base = (Expr*)nullptr; Result.InvalidBase = false; Result.Offset = CharUnits::fromQuantity(N); Result.CallIndex = 0; Result.Designator.setInvalid(); Result.IsNullPtr = false; return true; } else { // Cast is of an lvalue, no need to change value. Result.setFrom(Info.Ctx, Value); return true; } } case CK_ArrayToPointerDecay: if (SubExpr->isGLValue()) { - if (!EvaluateLValue(SubExpr, Result, Info)) + if (!evaluateLValue(SubExpr, Result)) return false; } else { Result.set(SubExpr, Info.CurrentCall->Index); if (!EvaluateInPlace(Info.CurrentCall->createTemporary(SubExpr, false), Info, Result, SubExpr)) return false; } // The result is a pointer to the first element of the array. if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(SubExpr->getType())) Result.addArray(Info, E, CAT); else Result.Designator.setInvalid(); return true; case CK_FunctionToPointerDecay: - return EvaluateLValue(SubExpr, Result, Info); + return evaluateLValue(SubExpr, Result); case CK_LValueToRValue: { LValue LVal; - if (!EvaluateLValue(E->getSubExpr(), LVal, Info)) + if (!evaluateLValue(E->getSubExpr(), LVal)) return false; APValue RVal; // Note, we use the subexpression's type in order to retain cv-qualifiers. if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(), LVal, RVal)) - return evaluateLValueAsAllocSize(Info, LVal.Base, Result); + return InvalidBaseOK && + evaluateLValueAsAllocSize(Info, LVal.Base, Result); return Success(RVal, E); } } return ExprEvaluatorBaseTy::VisitCastExpr(E); } static CharUnits GetAlignOfType(EvalInfo &Info, QualType T) { // C++ [expr.alignof]p3: // When alignof is applied to a reference type, the result is the // alignment of the referenced type. if (const ReferenceType *Ref = T->getAs()) T = Ref->getPointeeType(); // __alignof is defined to return the preferred alignment. return Info.Ctx.toCharUnitsFromBits( Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); } static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) { E = E->IgnoreParens(); // The kinds of expressions that we have special-case logic here for // should be kept up to date with the special checks for those // expressions in Sema. // alignof decl is always accepted, even if it doesn't make sense: we default // to 1 in those cases. if (const DeclRefExpr *DRE = dyn_cast(E)) return Info.Ctx.getDeclAlign(DRE->getDecl(), /*RefAsPointee*/true); if (const MemberExpr *ME = dyn_cast(E)) return Info.Ctx.getDeclAlign(ME->getMemberDecl(), /*RefAsPointee*/true); return GetAlignOfType(Info, E->getType()); } // To be clear: this happily visits unsupported builtins. Better name welcomed. bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) { if (ExprEvaluatorBaseTy::VisitCallExpr(E)) return true; - if (!(Info.allowInvalidBaseExpr() && getAllocSizeAttr(E))) + if (!(InvalidBaseOK && getAllocSizeAttr(E))) return false; Result.setInvalid(E); QualType PointeeTy = E->getType()->castAs()->getPointeeType(); Result.addUnsizedArray(Info, PointeeTy); return true; } bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) { if (IsStringLiteralCall(E)) return Success(E); if (unsigned BuiltinOp = E->getBuiltinCallee()) return VisitBuiltinCallExpr(E, BuiltinOp); return visitNonBuiltinCallExpr(E); } bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { switch (BuiltinOp) { case Builtin::BI__builtin_addressof: - return EvaluateLValue(E->getArg(0), Result, Info); + return evaluateLValue(E->getArg(0), Result); case Builtin::BI__builtin_assume_aligned: { // We need to be very careful here because: if the pointer does not have the // asserted alignment, then the behavior is undefined, and undefined // behavior is non-constant. - if (!EvaluatePointer(E->getArg(0), Result, Info)) + if (!evaluatePointer(E->getArg(0), Result)) return false; LValue OffsetResult(Result); APSInt Alignment; if (!EvaluateInteger(E->getArg(1), Alignment, Info)) return false; CharUnits Align = CharUnits::fromQuantity(getExtValue(Alignment)); if (E->getNumArgs() > 2) { APSInt Offset; if (!EvaluateInteger(E->getArg(2), Offset, Info)) return false; int64_t AdditionalOffset = -getExtValue(Offset); OffsetResult.Offset += CharUnits::fromQuantity(AdditionalOffset); } // If there is a base object, then it must have the correct alignment. if (OffsetResult.Base) { CharUnits BaseAlignment; if (const ValueDecl *VD = OffsetResult.Base.dyn_cast()) { BaseAlignment = Info.Ctx.getDeclAlign(VD); } else { BaseAlignment = GetAlignOfExpr(Info, OffsetResult.Base.get()); } if (BaseAlignment < Align) { Result.Designator.setInvalid(); // FIXME: Quantities here cast to integers because the plural modifier // does not work on APSInts yet. CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment) << 0 << (int) BaseAlignment.getQuantity() << (unsigned) getExtValue(Alignment); return false; } } // The offset must also have the correct alignment. if (OffsetResult.Offset.alignTo(Align) != OffsetResult.Offset) { Result.Designator.setInvalid(); APSInt Offset(64, false); Offset = OffsetResult.Offset.getQuantity(); if (OffsetResult.Base) CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment) << 1 << (int) getExtValue(Offset) << (unsigned) getExtValue(Alignment); else CCEDiag(E->getArg(0), diag::note_constexpr_baa_value_insufficient_alignment) << Offset << (unsigned) getExtValue(Alignment); return false; } return true; } case Builtin::BIstrchr: case Builtin::BIwcschr: case Builtin::BImemchr: case Builtin::BIwmemchr: if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); // Fall through. case Builtin::BI__builtin_strchr: case Builtin::BI__builtin_wcschr: case Builtin::BI__builtin_memchr: case Builtin::BI__builtin_char_memchr: case Builtin::BI__builtin_wmemchr: { if (!Visit(E->getArg(0))) return false; APSInt Desired; if (!EvaluateInteger(E->getArg(1), Desired, Info)) return false; uint64_t MaxLength = uint64_t(-1); if (BuiltinOp != Builtin::BIstrchr && BuiltinOp != Builtin::BIwcschr && BuiltinOp != Builtin::BI__builtin_strchr && BuiltinOp != Builtin::BI__builtin_wcschr) { APSInt N; if (!EvaluateInteger(E->getArg(2), N, Info)) return false; MaxLength = N.getExtValue(); } QualType CharTy = E->getArg(0)->getType()->getPointeeType(); // Figure out what value we're actually looking for (after converting to // the corresponding unsigned type if necessary). uint64_t DesiredVal; bool StopAtNull = false; switch (BuiltinOp) { case Builtin::BIstrchr: case Builtin::BI__builtin_strchr: // strchr compares directly to the passed integer, and therefore // always fails if given an int that is not a char. if (!APSInt::isSameValue(HandleIntToIntCast(Info, E, CharTy, E->getArg(1)->getType(), Desired), Desired)) return ZeroInitialization(E); StopAtNull = true; // Fall through. case Builtin::BImemchr: case Builtin::BI__builtin_memchr: case Builtin::BI__builtin_char_memchr: // memchr compares by converting both sides to unsigned char. That's also // correct for strchr if we get this far (to cope with plain char being // unsigned in the strchr case). DesiredVal = Desired.trunc(Info.Ctx.getCharWidth()).getZExtValue(); break; case Builtin::BIwcschr: case Builtin::BI__builtin_wcschr: StopAtNull = true; // Fall through. case Builtin::BIwmemchr: case Builtin::BI__builtin_wmemchr: // wcschr and wmemchr are given a wchar_t to look for. Just use it. DesiredVal = Desired.getZExtValue(); break; } for (; MaxLength; --MaxLength) { APValue Char; if (!handleLValueToRValueConversion(Info, E, CharTy, Result, Char) || !Char.isInt()) return false; if (Char.getInt().getZExtValue() == DesiredVal) return true; if (StopAtNull && !Char.getInt()) break; if (!HandleLValueArrayAdjustment(Info, E, Result, CharTy, 1)) return false; } // Not found: return nullptr. return ZeroInitialization(E); } default: return visitNonBuiltinCallExpr(E); } } //===----------------------------------------------------------------------===// // Member Pointer Evaluation //===----------------------------------------------------------------------===// namespace { class MemberPointerExprEvaluator : public ExprEvaluatorBase { MemberPtr &Result; bool Success(const ValueDecl *D) { Result = MemberPtr(D); return true; } public: MemberPointerExprEvaluator(EvalInfo &Info, MemberPtr &Result) : ExprEvaluatorBaseTy(Info), Result(Result) {} bool Success(const APValue &V, const Expr *E) { Result.setFrom(V); return true; } bool ZeroInitialization(const Expr *E) { return Success((const ValueDecl*)nullptr); } bool VisitCastExpr(const CastExpr *E); bool VisitUnaryAddrOf(const UnaryOperator *E); }; } // end anonymous namespace static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isMemberPointerType()); return MemberPointerExprEvaluator(Info, Result).Visit(E); } bool MemberPointerExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_NullToMemberPointer: VisitIgnoredValue(E->getSubExpr()); return ZeroInitialization(E); case CK_BaseToDerivedMemberPointer: { if (!Visit(E->getSubExpr())) return false; if (E->path_empty()) return true; // Base-to-derived member pointer casts store the path in derived-to-base // order, so iterate backwards. The CXXBaseSpecifier also provides us with // the wrong end of the derived->base arc, so stagger the path by one class. typedef std::reverse_iterator ReverseIter; for (ReverseIter PathI(E->path_end() - 1), PathE(E->path_begin()); PathI != PathE; ++PathI) { assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); const CXXRecordDecl *Derived = (*PathI)->getType()->getAsCXXRecordDecl(); if (!Result.castToDerived(Derived)) return Error(E); } const Type *FinalTy = E->getType()->castAs()->getClass(); if (!Result.castToDerived(FinalTy->getAsCXXRecordDecl())) return Error(E); return true; } case CK_DerivedToBaseMemberPointer: if (!Visit(E->getSubExpr())) return false; for (CastExpr::path_const_iterator PathI = E->path_begin(), PathE = E->path_end(); PathI != PathE; ++PathI) { assert(!(*PathI)->isVirtual() && "memptr cast through vbase"); const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); if (!Result.castToBase(Base)) return Error(E); } return true; } } bool MemberPointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) { // C++11 [expr.unary.op]p3 has very strict rules on how the address of a // member can be formed. return Success(cast(E->getSubExpr())->getDecl()); } //===----------------------------------------------------------------------===// // Record Evaluation //===----------------------------------------------------------------------===// namespace { class RecordExprEvaluator : public ExprEvaluatorBase { const LValue &This; APValue &Result; public: RecordExprEvaluator(EvalInfo &info, const LValue &This, APValue &Result) : ExprEvaluatorBaseTy(info), This(This), Result(Result) {} bool Success(const APValue &V, const Expr *E) { Result = V; return true; } bool ZeroInitialization(const Expr *E) { return ZeroInitialization(E, E->getType()); } bool ZeroInitialization(const Expr *E, QualType T); bool VisitCallExpr(const CallExpr *E) { return handleCallExpr(E, Result, &This); } bool VisitCastExpr(const CastExpr *E); bool VisitInitListExpr(const InitListExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, E->getType()); } bool VisitLambdaExpr(const LambdaExpr *E); bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T); bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); }; } /// Perform zero-initialization on an object of non-union class type. /// C++11 [dcl.init]p5: /// To zero-initialize an object or reference of type T means: /// [...] /// -- if T is a (possibly cv-qualified) non-union class type, /// each non-static data member and each base-class subobject is /// zero-initialized static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, const RecordDecl *RD, const LValue &This, APValue &Result) { assert(!RD->isUnion() && "Expected non-union class type"); const CXXRecordDecl *CD = dyn_cast(RD); Result = APValue(APValue::UninitStruct(), CD ? CD->getNumBases() : 0, std::distance(RD->field_begin(), RD->field_end())); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); if (CD) { unsigned Index = 0; for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(), End = CD->bases_end(); I != End; ++I, ++Index) { const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl(); LValue Subobject = This; if (!HandleLValueDirectBase(Info, E, Subobject, CD, Base, &Layout)) return false; if (!HandleClassZeroInitialization(Info, E, Base, Subobject, Result.getStructBase(Index))) return false; } } for (const auto *I : RD->fields()) { // -- if T is a reference type, no initialization is performed. if (I->getType()->isReferenceType()) continue; LValue Subobject = This; if (!HandleLValueMember(Info, E, Subobject, I, &Layout)) return false; ImplicitValueInitExpr VIE(I->getType()); if (!EvaluateInPlace( Result.getStructField(I->getFieldIndex()), Info, Subobject, &VIE)) return false; } return true; } bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) { const RecordDecl *RD = T->castAs()->getDecl(); if (RD->isInvalidDecl()) return false; if (RD->isUnion()) { // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the // object's first non-static named data member is zero-initialized RecordDecl::field_iterator I = RD->field_begin(); if (I == RD->field_end()) { Result = APValue((const FieldDecl*)nullptr); return true; } LValue Subobject = This; if (!HandleLValueMember(Info, E, Subobject, *I)) return false; Result = APValue(*I); ImplicitValueInitExpr VIE(I->getType()); return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, &VIE); } if (isa(RD) && cast(RD)->getNumVBases()) { Info.FFDiag(E, diag::note_constexpr_virtual_base) << RD; return false; } return HandleClassZeroInitialization(Info, E, RD, This, Result); } bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_ConstructorConversion: return Visit(E->getSubExpr()); case CK_DerivedToBase: case CK_UncheckedDerivedToBase: { APValue DerivedObject; if (!Evaluate(DerivedObject, Info, E->getSubExpr())) return false; if (!DerivedObject.isStruct()) return Error(E->getSubExpr()); // Derived-to-base rvalue conversion: just slice off the derived part. APValue *Value = &DerivedObject; const CXXRecordDecl *RD = E->getSubExpr()->getType()->getAsCXXRecordDecl(); for (CastExpr::path_const_iterator PathI = E->path_begin(), PathE = E->path_end(); PathI != PathE; ++PathI) { assert(!(*PathI)->isVirtual() && "record rvalue with virtual base"); const CXXRecordDecl *Base = (*PathI)->getType()->getAsCXXRecordDecl(); Value = &Value->getStructBase(getBaseIndex(RD, Base)); RD = Base; } Result = *Value; return true; } } } bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { if (E->isTransparent()) return Visit(E->getInit(0)); const RecordDecl *RD = E->getType()->castAs()->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); if (RD->isUnion()) { const FieldDecl *Field = E->getInitializedFieldInUnion(); Result = APValue(Field); if (!Field) return true; // If the initializer list for a union does not contain any elements, the // first element of the union is value-initialized. // FIXME: The element should be initialized from an initializer list. // Is this difference ever observable for initializer lists which // we don't build? ImplicitValueInitExpr VIE(Field->getType()); const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE; LValue Subobject = This; if (!HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout)) return false; // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, isa(InitExpr)); return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr); } auto *CXXRD = dyn_cast(RD); if (Result.isUninit()) Result = APValue(APValue::UninitStruct(), CXXRD ? CXXRD->getNumBases() : 0, std::distance(RD->field_begin(), RD->field_end())); unsigned ElementNo = 0; bool Success = true; // Initialize base classes. if (CXXRD) { for (const auto &Base : CXXRD->bases()) { assert(ElementNo < E->getNumInits() && "missing init for base class"); const Expr *Init = E->getInit(ElementNo); LValue Subobject = This; if (!HandleLValueBase(Info, Init, Subobject, CXXRD, &Base)) return false; APValue &FieldVal = Result.getStructBase(ElementNo); if (!EvaluateInPlace(FieldVal, Info, Subobject, Init)) { if (!Info.noteFailure()) return false; Success = false; } ++ElementNo; } } // Initialize members. for (const auto *Field : RD->fields()) { // Anonymous bit-fields are not considered members of the class for // purposes of aggregate initialization. if (Field->isUnnamedBitfield()) continue; LValue Subobject = This; bool HaveInit = ElementNo < E->getNumInits(); // FIXME: Diagnostics here should point to the end of the initializer // list, not the start. if (!HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E, Subobject, Field, &Layout)) return false; // Perform an implicit value-initialization for members beyond the end of // the initializer list. ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType()); const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE; // Temporarily override This, in case there's a CXXDefaultInitExpr in here. ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This, isa(Init)); APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) || (Field->isBitField() && !truncateBitfieldValue(Info, Init, FieldVal, Field))) { if (!Info.noteFailure()) return false; Success = false; } } return Success; } bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T) { // Note that E's type is not necessarily the type of our class here; we might // be initializing an array element instead. const CXXConstructorDecl *FD = E->getConstructor(); if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) return false; bool ZeroInit = E->requiresZeroInitialization(); if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) { // If we've already performed zero-initialization, we're already done. if (!Result.isUninit()) return true; // We can get here in two different ways: // 1) We're performing value-initialization, and should zero-initialize // the object, or // 2) We're performing default-initialization of an object with a trivial // constexpr default constructor, in which case we should start the // lifetimes of all the base subobjects (there can be no data member // subobjects in this case) per [basic.life]p1. // Either way, ZeroInitialization is appropriate. return ZeroInitialization(E, T); } const FunctionDecl *Definition = nullptr; auto Body = FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; // Avoid materializing a temporary for an elidable copy/move constructor. if (E->isElidable() && !ZeroInit) if (const MaterializeTemporaryExpr *ME = dyn_cast(E->getArg(0))) return Visit(ME->GetTemporaryExpr()); if (ZeroInit && !ZeroInitialization(E, T)) return false; auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs()); return HandleConstructorCall(E, This, Args, cast(Definition), Info, Result); } bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr( const CXXInheritedCtorInitExpr *E) { if (!Info.CurrentCall) { assert(Info.checkingPotentialConstantExpression()); return false; } const CXXConstructorDecl *FD = E->getConstructor(); if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) return false; const FunctionDecl *Definition = nullptr; auto Body = FD->getBody(Definition); if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body)) return false; return HandleConstructorCall(E, This, Info.CurrentCall->Arguments, cast(Definition), Info, Result); } bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( const CXXStdInitializerListExpr *E) { const ConstantArrayType *ArrayType = Info.Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); LValue Array; if (!EvaluateLValue(E->getSubExpr(), Array, Info)) return false; // Get a pointer to the first element of the array. Array.addArray(Info, E, ArrayType); // FIXME: Perform the checks on the field types in SemaInit. RecordDecl *Record = E->getType()->castAs()->getDecl(); RecordDecl::field_iterator Field = Record->field_begin(); if (Field == Record->field_end()) return Error(E); // Start pointer. if (!Field->getType()->isPointerType() || !Info.Ctx.hasSameType(Field->getType()->getPointeeType(), ArrayType->getElementType())) return Error(E); // FIXME: What if the initializer_list type has base classes, etc? Result = APValue(APValue::UninitStruct(), 0, 2); Array.moveInto(Result.getStructField(0)); if (++Field == Record->field_end()) return Error(E); if (Field->getType()->isPointerType() && Info.Ctx.hasSameType(Field->getType()->getPointeeType(), ArrayType->getElementType())) { // End pointer. if (!HandleLValueArrayAdjustment(Info, E, Array, ArrayType->getElementType(), ArrayType->getSize().getZExtValue())) return false; Array.moveInto(Result.getStructField(1)); } else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType())) // Length. Result.getStructField(1) = APValue(APSInt(ArrayType->getSize())); else return Error(E); if (++Field != Record->field_end()) return Error(E); return true; } bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { const CXXRecordDecl *ClosureClass = E->getLambdaClass(); if (ClosureClass->isInvalidDecl()) return false; if (Info.checkingPotentialConstantExpression()) return true; if (E->capture_size()) { Info.FFDiag(E, diag::note_unimplemented_constexpr_lambda_feature_ast) << "can not evaluate lambda expressions with captures"; return false; } // FIXME: Implement captures. Result = APValue(APValue::UninitStruct(), /*NumBases*/0, /*NumFields*/0); return true; } static bool EvaluateRecord(const Expr *E, const LValue &This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRecordType() && "can't evaluate expression as a record rvalue"); return RecordExprEvaluator(Info, This, Result).Visit(E); } //===----------------------------------------------------------------------===// // Temporary Evaluation // // Temporaries are represented in the AST as rvalues, but generally behave like // lvalues. The full-object of which the temporary is a subobject is implicitly // materialized so that a reference can bind to it. //===----------------------------------------------------------------------===// namespace { class TemporaryExprEvaluator : public LValueExprEvaluatorBase { public: TemporaryExprEvaluator(EvalInfo &Info, LValue &Result) : - LValueExprEvaluatorBaseTy(Info, Result) {} + LValueExprEvaluatorBaseTy(Info, Result, false) {} /// Visit an expression which constructs the value of this temporary. bool VisitConstructExpr(const Expr *E) { Result.set(E, Info.CurrentCall->Index); return EvaluateInPlace(Info.CurrentCall->createTemporary(E, false), Info, Result, E); } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return LValueExprEvaluatorBaseTy::VisitCastExpr(E); case CK_ConstructorConversion: return VisitConstructExpr(E->getSubExpr()); } } bool VisitInitListExpr(const InitListExpr *E) { return VisitConstructExpr(E); } bool VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitConstructExpr(E); } bool VisitCallExpr(const CallExpr *E) { return VisitConstructExpr(E); } bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E) { return VisitConstructExpr(E); } bool VisitLambdaExpr(const LambdaExpr *E) { return VisitConstructExpr(E); } }; } // end anonymous namespace /// Evaluate an expression of record type as a temporary. static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRecordType()); return TemporaryExprEvaluator(Info, Result).Visit(E); } //===----------------------------------------------------------------------===// // Vector Evaluation //===----------------------------------------------------------------------===// namespace { class VectorExprEvaluator : public ExprEvaluatorBase { APValue &Result; public: VectorExprEvaluator(EvalInfo &info, APValue &Result) : ExprEvaluatorBaseTy(info), Result(Result) {} bool Success(ArrayRef V, const Expr *E) { assert(V.size() == E->getType()->castAs()->getNumElements()); // FIXME: remove this APValue copy. Result = APValue(V.data(), V.size()); return true; } bool Success(const APValue &V, const Expr *E) { assert(V.isVector()); Result = V; return true; } bool ZeroInitialization(const Expr *E); bool VisitUnaryReal(const UnaryOperator *E) { return Visit(E->getSubExpr()); } bool VisitCastExpr(const CastExpr* E); bool VisitInitListExpr(const InitListExpr *E); bool VisitUnaryImag(const UnaryOperator *E); // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div, // binary comparisons, binary and/or/xor, // shufflevector, ExtVectorElementExpr }; } // end anonymous namespace static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isVectorType() &&"not a vector rvalue"); return VectorExprEvaluator(Info, Result).Visit(E); } bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) { const VectorType *VTy = E->getType()->castAs(); unsigned NElts = VTy->getNumElements(); const Expr *SE = E->getSubExpr(); QualType SETy = SE->getType(); switch (E->getCastKind()) { case CK_VectorSplat: { APValue Val = APValue(); if (SETy->isIntegerType()) { APSInt IntResult; if (!EvaluateInteger(SE, IntResult, Info)) return false; Val = APValue(std::move(IntResult)); } else if (SETy->isRealFloatingType()) { APFloat FloatResult(0.0); if (!EvaluateFloat(SE, FloatResult, Info)) return false; Val = APValue(std::move(FloatResult)); } else { return Error(E); } // Splat and create vector APValue. SmallVector Elts(NElts, Val); return Success(Elts, E); } case CK_BitCast: { // Evaluate the operand into an APInt we can extract from. llvm::APInt SValInt; if (!EvalAndBitcastToAPInt(Info, SE, SValInt)) return false; // Extract the elements QualType EltTy = VTy->getElementType(); unsigned EltSize = Info.Ctx.getTypeSize(EltTy); bool BigEndian = Info.Ctx.getTargetInfo().isBigEndian(); SmallVector Elts; if (EltTy->isRealFloatingType()) { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy); unsigned FloatEltSize = EltSize; if (&Sem == &APFloat::x87DoubleExtended()) FloatEltSize = 80; for (unsigned i = 0; i < NElts; i++) { llvm::APInt Elt; if (BigEndian) Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize); else Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize); Elts.push_back(APValue(APFloat(Sem, Elt))); } } else if (EltTy->isIntegerType()) { for (unsigned i = 0; i < NElts; i++) { llvm::APInt Elt; if (BigEndian) Elt = SValInt.rotl(i*EltSize+EltSize).zextOrTrunc(EltSize); else Elt = SValInt.rotr(i*EltSize).zextOrTrunc(EltSize); Elts.push_back(APValue(APSInt(Elt, EltTy->isSignedIntegerType()))); } } else { return Error(E); } return Success(Elts, E); } default: return ExprEvaluatorBaseTy::VisitCastExpr(E); } } bool VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { const VectorType *VT = E->getType()->castAs(); unsigned NumInits = E->getNumInits(); unsigned NumElements = VT->getNumElements(); QualType EltTy = VT->getElementType(); SmallVector Elements; // The number of initializers can be less than the number of // vector elements. For OpenCL, this can be due to nested vector // initialization. For GCC compatibility, missing trailing elements // should be initialized with zeroes. unsigned CountInits = 0, CountElts = 0; while (CountElts < NumElements) { // Handle nested vector initialization. if (CountInits < NumInits && E->getInit(CountInits)->getType()->isVectorType()) { APValue v; if (!EvaluateVector(E->getInit(CountInits), v, Info)) return Error(E); unsigned vlen = v.getVectorLength(); for (unsigned j = 0; j < vlen; j++) Elements.push_back(v.getVectorElt(j)); CountElts += vlen; } else if (EltTy->isIntegerType()) { llvm::APSInt sInt(32); if (CountInits < NumInits) { if (!EvaluateInteger(E->getInit(CountInits), sInt, Info)) return false; } else // trailing integer zero. sInt = Info.Ctx.MakeIntValue(0, EltTy); Elements.push_back(APValue(sInt)); CountElts++; } else { llvm::APFloat f(0.0); if (CountInits < NumInits) { if (!EvaluateFloat(E->getInit(CountInits), f, Info)) return false; } else // trailing float zero. f = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy)); Elements.push_back(APValue(f)); CountElts++; } CountInits++; } return Success(Elements, E); } bool VectorExprEvaluator::ZeroInitialization(const Expr *E) { const VectorType *VT = E->getType()->getAs(); QualType EltTy = VT->getElementType(); APValue ZeroElement; if (EltTy->isIntegerType()) ZeroElement = APValue(Info.Ctx.MakeIntValue(0, EltTy)); else ZeroElement = APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(EltTy))); SmallVector Elements(VT->getNumElements(), ZeroElement); return Success(Elements, E); } bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { VisitIgnoredValue(E->getSubExpr()); return ZeroInitialization(E); } //===----------------------------------------------------------------------===// // Array Evaluation //===----------------------------------------------------------------------===// namespace { class ArrayExprEvaluator : public ExprEvaluatorBase { const LValue &This; APValue &Result; public: ArrayExprEvaluator(EvalInfo &Info, const LValue &This, APValue &Result) : ExprEvaluatorBaseTy(Info), This(This), Result(Result) {} bool Success(const APValue &V, const Expr *E) { assert((V.isArray() || V.isLValue()) && "expected array or string literal"); Result = V; return true; } bool ZeroInitialization(const Expr *E) { const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType()); if (!CAT) return Error(E); Result = APValue(APValue::UninitArray(), 0, CAT->getSize().getZExtValue()); if (!Result.hasArrayFiller()) return true; // Zero-initialize all elements. LValue Subobject = This; Subobject.addArray(Info, E, CAT); ImplicitValueInitExpr VIE(CAT->getElementType()); return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, &VIE); } bool VisitCallExpr(const CallExpr *E) { return handleCallExpr(E, Result, &This); } bool VisitInitListExpr(const InitListExpr *E); bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E); bool VisitCXXConstructExpr(const CXXConstructExpr *E, const LValue &Subobject, APValue *Value, QualType Type); }; } // end anonymous namespace static bool EvaluateArray(const Expr *E, const LValue &This, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isArrayType() && "not an array rvalue"); return ArrayExprEvaluator(Info, This, Result).Visit(E); } bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(E->getType()); if (!CAT) return Error(E); // C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...] // an appropriately-typed string literal enclosed in braces. if (E->isStringLiteralInit()) { LValue LV; if (!EvaluateLValue(E->getInit(0), LV, Info)) return false; APValue Val; LV.moveInto(Val); return Success(Val, E); } bool Success = true; assert((!Result.isArray() || Result.getArrayInitializedElts() == 0) && "zero-initialized array shouldn't have any initialized elts"); APValue Filler; if (Result.isArray() && Result.hasArrayFiller()) Filler = Result.getArrayFiller(); unsigned NumEltsToInit = E->getNumInits(); unsigned NumElts = CAT->getSize().getZExtValue(); const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr; // If the initializer might depend on the array index, run it for each // array element. For now, just whitelist non-class value-initialization. if (NumEltsToInit != NumElts && !isa(FillerExpr)) NumEltsToInit = NumElts; Result = APValue(APValue::UninitArray(), NumEltsToInit, NumElts); // If the array was previously zero-initialized, preserve the // zero-initialized values. if (!Filler.isUninit()) { for (unsigned I = 0, E = Result.getArrayInitializedElts(); I != E; ++I) Result.getArrayInitializedElt(I) = Filler; if (Result.hasArrayFiller()) Result.getArrayFiller() = Filler; } LValue Subobject = This; Subobject.addArray(Info, E, CAT); for (unsigned Index = 0; Index != NumEltsToInit; ++Index) { const Expr *Init = Index < E->getNumInits() ? E->getInit(Index) : FillerExpr; if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), Info, Subobject, Init) || !HandleLValueArrayAdjustment(Info, Init, Subobject, CAT->getElementType(), 1)) { if (!Info.noteFailure()) return false; Success = false; } } if (!Result.hasArrayFiller()) return Success; // If we get here, we have a trivial filler, which we can just evaluate // once and splat over the rest of the array elements. assert(FillerExpr && "no array filler for incomplete init list"); return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject, FillerExpr) && Success; } bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { if (E->getCommonExpr() && !Evaluate(Info.CurrentCall->createTemporary(E->getCommonExpr(), false), Info, E->getCommonExpr()->getSourceExpr())) return false; auto *CAT = cast(E->getType()->castAsArrayTypeUnsafe()); uint64_t Elements = CAT->getSize().getZExtValue(); Result = APValue(APValue::UninitArray(), Elements, Elements); LValue Subobject = This; Subobject.addArray(Info, E, CAT); bool Success = true; for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) { if (!EvaluateInPlace(Result.getArrayInitializedElt(Index), Info, Subobject, E->getSubExpr()) || !HandleLValueArrayAdjustment(Info, E, Subobject, CAT->getElementType(), 1)) { if (!Info.noteFailure()) return false; Success = false; } } return Success; } bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) { return VisitCXXConstructExpr(E, This, &Result, E->getType()); } bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, const LValue &Subobject, APValue *Value, QualType Type) { bool HadZeroInit = !Value->isUninit(); if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) { unsigned N = CAT->getSize().getZExtValue(); // Preserve the array filler if we had prior zero-initialization. APValue Filler = HadZeroInit && Value->hasArrayFiller() ? Value->getArrayFiller() : APValue(); *Value = APValue(APValue::UninitArray(), N, N); if (HadZeroInit) for (unsigned I = 0; I != N; ++I) Value->getArrayInitializedElt(I) = Filler; // Initialize the elements. LValue ArrayElt = Subobject; ArrayElt.addArray(Info, E, CAT); for (unsigned I = 0; I != N; ++I) if (!VisitCXXConstructExpr(E, ArrayElt, &Value->getArrayInitializedElt(I), CAT->getElementType()) || !HandleLValueArrayAdjustment(Info, E, ArrayElt, CAT->getElementType(), 1)) return false; return true; } if (!Type->isRecordType()) return Error(E); return RecordExprEvaluator(Info, Subobject, *Value) .VisitCXXConstructExpr(E, Type); } //===----------------------------------------------------------------------===// // Integer Evaluation // // As a GNU extension, we support casting pointers to sufficiently-wide integer // types and back in constant folding. Integer values are thus represented // either as an integer-valued APValue, or as an lvalue-valued APValue. //===----------------------------------------------------------------------===// namespace { class IntExprEvaluator : public ExprEvaluatorBase { APValue &Result; public: IntExprEvaluator(EvalInfo &info, APValue &result) : ExprEvaluatorBaseTy(info), Result(result) {} bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); assert(SI.isSigned() == E->getType()->isSignedIntegerOrEnumerationType() && "Invalid evaluation result."); assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(SI); return true; } bool Success(const llvm::APSInt &SI, const Expr *E) { return Success(SI, E, Result); } bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) && "Invalid evaluation result."); Result = APValue(APSInt(I)); Result.getInt().setIsUnsigned( E->getType()->isUnsignedIntegerOrEnumerationType()); return true; } bool Success(const llvm::APInt &I, const Expr *E) { return Success(I, E, Result); } bool Success(uint64_t Value, const Expr *E, APValue &Result) { assert(E->getType()->isIntegralOrEnumerationType() && "Invalid evaluation result."); Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType())); return true; } bool Success(uint64_t Value, const Expr *E) { return Success(Value, E, Result); } bool Success(CharUnits Size, const Expr *E) { return Success(Size.getQuantity(), E); } bool Success(const APValue &V, const Expr *E) { if (V.isLValue() || V.isAddrLabelDiff()) { Result = V; return true; } return Success(V.getInt(), E); } bool ZeroInitialization(const Expr *E) { return Success(0, E); } //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); } bool VisitCharacterLiteral(const CharacterLiteral *E) { return Success(E->getValue(), E); } bool CheckReferencedDecl(const Expr *E, const Decl *D); bool VisitDeclRefExpr(const DeclRefExpr *E) { if (CheckReferencedDecl(E, E->getDecl())) return true; return ExprEvaluatorBaseTy::VisitDeclRefExpr(E); } bool VisitMemberExpr(const MemberExpr *E) { if (CheckReferencedDecl(E, E->getMemberDecl())) { VisitIgnoredBaseExpression(E->getBase()); return true; } return ExprEvaluatorBaseTy::VisitMemberExpr(E); } bool VisitCallExpr(const CallExpr *E); bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitOffsetOfExpr(const OffsetOfExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitCastExpr(const CastExpr* E); bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E); bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return Success(E->getValue(), E); } bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) { return Success(E->getValue(), E); } bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) { if (Info.ArrayInitIndex == uint64_t(-1)) { // We were asked to evaluate this subexpression independent of the // enclosing ArrayInitLoopExpr. We can't do that. Info.FFDiag(E); return false; } return Success(Info.ArrayInitIndex, E); } // Note, GNU defines __null as an integer, not a pointer. bool VisitGNUNullExpr(const GNUNullExpr *E) { return ZeroInitialization(E); } bool VisitTypeTraitExpr(const TypeTraitExpr *E) { return Success(E->getValue(), E); } bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { return Success(E->getValue(), E); } bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { return Success(E->getValue(), E); } bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace /// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed expression, and /// produce either the integer value or a pointer. /// /// GCC has a heinous extension which folds casts between pointer types and /// pointer-sized integral types. We support this by allowing the evaluation of /// an integer rvalue to produce a pointer (represented as an lvalue) instead. /// Some simple arithmetic on such values is supported (they are treated much /// like char*). static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isIntegralOrEnumerationType()); return IntExprEvaluator(Info, Result).Visit(E); } static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) { APValue Val; if (!EvaluateIntegerOrLValue(E, Val, Info)) return false; if (!Val.isInt()) { // FIXME: It would be better to produce the diagnostic for casting // a pointer to an integer. Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = Val.getInt(); return true; } /// Check whether the given declaration can be directly converted to an integral /// rvalue. If not, no diagnostic is produced; there are other things we can /// try. bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { // Enums are integer constant exprs. if (const EnumConstantDecl *ECD = dyn_cast(D)) { // Check for signedness/width mismatches between E type and ECD value. bool SameSign = (ECD->getInitVal().isSigned() == E->getType()->isSignedIntegerOrEnumerationType()); bool SameWidth = (ECD->getInitVal().getBitWidth() == Info.Ctx.getIntWidth(E->getType())); if (SameSign && SameWidth) return Success(ECD->getInitVal(), E); else { // Get rid of mismatch (otherwise Success assertions will fail) // by computing a new value matching the type of E. llvm::APSInt Val = ECD->getInitVal(); if (!SameSign) Val.setIsSigned(!ECD->getInitVal().isSigned()); if (!SameWidth) Val = Val.extOrTrunc(Info.Ctx.getIntWidth(E->getType())); return Success(Val, E); } } return false; } /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way /// as GCC. static int EvaluateBuiltinClassifyType(const CallExpr *E, const LangOptions &LangOpts) { // The following enum mimics the values returned by GCC. // FIXME: Does GCC differ between lvalue and rvalue references here? enum gcc_type_class { no_type_class = -1, void_type_class, integer_type_class, char_type_class, enumeral_type_class, boolean_type_class, pointer_type_class, reference_type_class, offset_type_class, real_type_class, complex_type_class, function_type_class, method_type_class, record_type_class, union_type_class, array_type_class, string_type_class, lang_type_class }; // If no argument was supplied, default to "no_type_class". This isn't // ideal, however it is what gcc does. if (E->getNumArgs() == 0) return no_type_class; QualType CanTy = E->getArg(0)->getType().getCanonicalType(); const BuiltinType *BT = dyn_cast(CanTy); switch (CanTy->getTypeClass()) { #define TYPE(ID, BASE) #define DEPENDENT_TYPE(ID, BASE) case Type::ID: #define NON_CANONICAL_TYPE(ID, BASE) case Type::ID: #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(ID, BASE) case Type::ID: #include "clang/AST/TypeNodes.def" llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); case Type::Builtin: switch (BT->getKind()) { #define BUILTIN_TYPE(ID, SINGLETON_ID) #define SIGNED_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return integer_type_class; #define FLOATING_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return real_type_class; #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: break; #include "clang/AST/BuiltinTypes.def" case BuiltinType::Void: return void_type_class; case BuiltinType::Bool: return boolean_type_class; case BuiltinType::Char_U: // gcc doesn't appear to use char_type_class case BuiltinType::UChar: case BuiltinType::UShort: case BuiltinType::UInt: case BuiltinType::ULong: case BuiltinType::ULongLong: case BuiltinType::UInt128: return integer_type_class; case BuiltinType::NullPtr: return pointer_type_class; case BuiltinType::WChar_U: case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ case BuiltinType::Id: #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::Dependent: llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); }; case Type::Enum: return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class; break; case Type::Pointer: return pointer_type_class; break; case Type::MemberPointer: if (CanTy->isMemberDataPointerType()) return offset_type_class; else { // We expect member pointers to be either data or function pointers, // nothing else. assert(CanTy->isMemberFunctionPointerType()); return method_type_class; } case Type::Complex: return complex_type_class; case Type::FunctionNoProto: case Type::FunctionProto: return LangOpts.CPlusPlus ? function_type_class : pointer_type_class; case Type::Record: if (const RecordType *RT = CanTy->getAs()) { switch (RT->getDecl()->getTagKind()) { case TagTypeKind::TTK_Struct: case TagTypeKind::TTK_Class: case TagTypeKind::TTK_Interface: return record_type_class; case TagTypeKind::TTK_Enum: return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class; case TagTypeKind::TTK_Union: return union_type_class; } } llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: return LangOpts.CPlusPlus ? array_type_class : pointer_type_class; case Type::BlockPointer: case Type::LValueReference: case Type::RValueReference: case Type::Vector: case Type::ExtVector: case Type::Auto: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: case Type::Pipe: case Type::Atomic: llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); } llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type"); } /// EvaluateBuiltinConstantPForLValue - Determine the result of /// __builtin_constant_p when applied to the given lvalue. /// /// An lvalue is only "constant" if it is a pointer or reference to the first /// character of a string literal. template static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) { const Expr *E = LV.getLValueBase().template dyn_cast(); return E && isa(E) && LV.getLValueOffset().isZero(); } /// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to /// GCC as we can manage. static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) { QualType ArgType = Arg->getType(); // __builtin_constant_p always has one operand. The rules which gcc follows // are not precisely documented, but are as follows: // // - If the operand is of integral, floating, complex or enumeration type, // and can be folded to a known value of that type, it returns 1. // - If the operand and can be folded to a pointer to the first character // of a string literal (or such a pointer cast to an integral type), it // returns 1. // // Otherwise, it returns 0. // // FIXME: GCC also intends to return 1 for literals of aggregate types, but // its support for this does not currently work. if (ArgType->isIntegralOrEnumerationType()) { Expr::EvalResult Result; if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects) return false; APValue &V = Result.Val; if (V.getKind() == APValue::Int) return true; if (V.getKind() == APValue::LValue) return EvaluateBuiltinConstantPForLValue(V); } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) { return Arg->isEvaluatable(Ctx); } else if (ArgType->isPointerType() || Arg->isGLValue()) { LValue LV; Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info) : EvaluatePointer(Arg, LV, Info)) && !Status.HasSideEffects) return EvaluateBuiltinConstantPForLValue(LV); } // Anything else isn't considered to be sufficiently constant. return false; } /// Retrieves the "underlying object type" of the given expression, /// as used by __builtin_object_size. static QualType getObjectType(APValue::LValueBase B) { if (const ValueDecl *D = B.dyn_cast()) { if (const VarDecl *VD = dyn_cast(D)) return VD->getType(); } else if (const Expr *E = B.get()) { if (isa(E)) return E->getType(); } return QualType(); } /// A more selective version of E->IgnoreParenCasts for /// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only /// to change the type of E. /// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo` /// /// Always returns an RValue with a pointer representation. static const Expr *ignorePointerCastsAndParens(const Expr *E) { assert(E->isRValue() && E->getType()->hasPointerRepresentation()); auto *NoParens = E->IgnoreParens(); auto *Cast = dyn_cast(NoParens); if (Cast == nullptr) return NoParens; // We only conservatively allow a few kinds of casts, because this code is // inherently a simple solution that seeks to support the common case. auto CastKind = Cast->getCastKind(); if (CastKind != CK_NoOp && CastKind != CK_BitCast && CastKind != CK_AddressSpaceConversion) return NoParens; auto *SubExpr = Cast->getSubExpr(); if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isRValue()) return NoParens; return ignorePointerCastsAndParens(SubExpr); } /// Checks to see if the given LValue's Designator is at the end of the LValue's /// record layout. e.g. /// struct { struct { int a, b; } fst, snd; } obj; /// obj.fst // no /// obj.snd // yes /// obj.fst.a // no /// obj.fst.b // no /// obj.snd.a // no /// obj.snd.b // yes /// /// Please note: this function is specialized for how __builtin_object_size /// views "objects". /// /// If this encounters an invalid RecordDecl, it will always return true. static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { assert(!LVal.Designator.Invalid); auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD, bool &Invalid) { const RecordDecl *Parent = FD->getParent(); Invalid = Parent->isInvalidDecl(); if (Invalid || Parent->isUnion()) return true; const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent); return FD->getFieldIndex() + 1 == Layout.getFieldCount(); }; auto &Base = LVal.getLValueBase(); if (auto *ME = dyn_cast_or_null(Base.dyn_cast())) { if (auto *FD = dyn_cast(ME->getMemberDecl())) { bool Invalid; if (!IsLastOrInvalidFieldDecl(FD, Invalid)) return Invalid; } else if (auto *IFD = dyn_cast(ME->getMemberDecl())) { for (auto *FD : IFD->chain()) { bool Invalid; if (!IsLastOrInvalidFieldDecl(cast(FD), Invalid)) return Invalid; } } } unsigned I = 0; QualType BaseType = getType(Base); if (LVal.Designator.FirstEntryIsAnUnsizedArray) { assert(isBaseAnAllocSizeCall(Base) && "Unsized array in non-alloc_size call?"); // If this is an alloc_size base, we should ignore the initial array index ++I; BaseType = BaseType->castAs()->getPointeeType(); } for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) { const auto &Entry = LVal.Designator.Entries[I]; if (BaseType->isArrayType()) { // Because __builtin_object_size treats arrays as objects, we can ignore // the index iff this is the last array in the Designator. if (I + 1 == E) return true; const auto *CAT = cast(Ctx.getAsArrayType(BaseType)); uint64_t Index = Entry.ArrayIndex; if (Index + 1 != CAT->getSize()) return false; BaseType = CAT->getElementType(); } else if (BaseType->isAnyComplexType()) { const auto *CT = BaseType->castAs(); uint64_t Index = Entry.ArrayIndex; if (Index != 1) return false; BaseType = CT->getElementType(); } else if (auto *FD = getAsField(Entry)) { bool Invalid; if (!IsLastOrInvalidFieldDecl(FD, Invalid)) return Invalid; BaseType = FD->getType(); } else { assert(getAsBaseClass(Entry) && "Expecting cast to a base class"); return false; } } return true; } /// Tests to see if the LValue has a user-specified designator (that isn't /// necessarily valid). Note that this always returns 'true' if the LValue has /// an unsized array as its first designator entry, because there's currently no /// way to tell if the user typed *foo or foo[0]. static bool refersToCompleteObject(const LValue &LVal) { if (LVal.Designator.Invalid) return false; if (!LVal.Designator.Entries.empty()) return LVal.Designator.isMostDerivedAnUnsizedArray(); if (!LVal.InvalidBase) return true; // If `E` is a MemberExpr, then the first part of the designator is hiding in // the LValueBase. const auto *E = LVal.Base.dyn_cast(); return !E || !isa(E); } /// Attempts to detect a user writing into a piece of memory that's impossible /// to figure out the size of by just using types. static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) { const SubobjectDesignator &Designator = LVal.Designator; // Notes: // - Users can only write off of the end when we have an invalid base. Invalid // bases imply we don't know where the memory came from. // - We used to be a bit more aggressive here; we'd only be conservative if // the array at the end was flexible, or if it had 0 or 1 elements. This // broke some common standard library extensions (PR30346), but was // otherwise seemingly fine. It may be useful to reintroduce this behavior // with some sort of whitelist. OTOH, it seems that GCC is always // conservative with the last element in structs (if it's an array), so our // current behavior is more compatible than a whitelisting approach would // be. return LVal.InvalidBase && Designator.Entries.size() == Designator.MostDerivedPathLength && Designator.MostDerivedIsArrayElement && isDesignatorAtObjectEnd(Ctx, LVal); } /// Converts the given APInt to CharUnits, assuming the APInt is unsigned. /// Fails if the conversion would cause loss of precision. static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int, CharUnits &Result) { auto CharUnitsMax = std::numeric_limits::max(); if (Int.ugt(CharUnitsMax)) return false; Result = CharUnits::fromQuantity(Int.getZExtValue()); return true; } /// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will /// determine how many bytes exist from the beginning of the object to either /// the end of the current subobject, or the end of the object itself, depending /// on what the LValue looks like + the value of Type. /// /// If this returns false, the value of Result is undefined. static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc, unsigned Type, const LValue &LVal, CharUnits &EndOffset) { bool DetermineForCompleteObject = refersToCompleteObject(LVal); auto CheckedHandleSizeof = [&](QualType Ty, CharUnits &Result) { if (Ty.isNull() || Ty->isIncompleteType() || Ty->isFunctionType()) return false; return HandleSizeof(Info, ExprLoc, Ty, Result); }; // We want to evaluate the size of the entire object. This is a valid fallback // for when Type=1 and the designator is invalid, because we're asked for an // upper-bound. if (!(Type & 1) || LVal.Designator.Invalid || DetermineForCompleteObject) { // Type=3 wants a lower bound, so we can't fall back to this. if (Type == 3 && !DetermineForCompleteObject) return false; llvm::APInt APEndOffset; if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); if (LVal.InvalidBase) return false; QualType BaseTy = getObjectType(LVal.getLValueBase()); return CheckedHandleSizeof(BaseTy, EndOffset); } // We want to evaluate the size of a subobject. const SubobjectDesignator &Designator = LVal.Designator; // The following is a moderately common idiom in C: // // struct Foo { int a; char c[1]; }; // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar)); // strcpy(&F->c[0], Bar); // // In order to not break too much legacy code, we need to support it. if (isUserWritingOffTheEnd(Info.Ctx, LVal)) { // If we can resolve this to an alloc_size call, we can hand that back, // because we know for certain how many bytes there are to write to. llvm::APInt APEndOffset; if (isBaseAnAllocSizeCall(LVal.getLValueBase()) && getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset)) return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset); // If we cannot determine the size of the initial allocation, then we can't // given an accurate upper-bound. However, we are still able to give // conservative lower-bounds for Type=3. if (Type == 1) return false; } CharUnits BytesPerElem; if (!CheckedHandleSizeof(Designator.MostDerivedType, BytesPerElem)) return false; // According to the GCC documentation, we want the size of the subobject // denoted by the pointer. But that's not quite right -- what we actually // want is the size of the immediately-enclosing array, if there is one. int64_t ElemsRemaining; if (Designator.MostDerivedIsArrayElement && Designator.Entries.size() == Designator.MostDerivedPathLength) { uint64_t ArraySize = Designator.getMostDerivedArraySize(); uint64_t ArrayIndex = Designator.Entries.back().ArrayIndex; ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex; } else { ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1; } EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining; return true; } /// \brief Tries to evaluate the __builtin_object_size for @p E. If successful, /// returns true and stores the result in @p Size. /// /// If @p WasError is non-null, this will report whether the failure to evaluate /// is to be treated as an Error in IntExprEvaluator. static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, EvalInfo &Info, uint64_t &Size) { // Determine the denoted object. LValue LVal; { // The operand of __builtin_object_size is never evaluated for side-effects. // If there are any, but we can determine the pointed-to object anyway, then // ignore the side-effects. SpeculativeEvaluationRAII SpeculativeEval(Info); FoldOffsetRAII Fold(Info); if (E->isGLValue()) { // It's possible for us to be given GLValues if we're called via // Expr::tryEvaluateObjectSize. APValue RVal; if (!EvaluateAsRValue(Info, E, RVal)) return false; LVal.setFrom(Info.Ctx, RVal); - } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info)) + } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info, + /*InvalidBaseOK=*/true)) return false; } // If we point to before the start of the object, there are no accessible // bytes. if (LVal.getLValueOffset().isNegative()) { Size = 0; return true; } CharUnits EndOffset; if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset)) return false; // If we've fallen outside of the end offset, just pretend there's nothing to // write to/read from. if (EndOffset <= LVal.getLValueOffset()) Size = 0; else Size = (EndOffset - LVal.getLValueOffset()).getQuantity(); return true; } bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { if (unsigned BuiltinOp = E->getBuiltinCallee()) return VisitBuiltinCallExpr(E, BuiltinOp); return ExprEvaluatorBaseTy::VisitCallExpr(E); } bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp) { switch (unsigned BuiltinOp = E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__builtin_object_size: { // The type was checked when we built the expression. unsigned Type = E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); assert(Type <= 3 && "unexpected type"); uint64_t Size; if (tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size)) return Success(Size, E); if (E->getArg(0)->HasSideEffects(Info.Ctx)) return Success((Type & 2) ? 0 : -1, E); // Expression had no side effects, but we couldn't statically determine the // size of the referenced object. switch (Info.EvalMode) { case EvalInfo::EM_ConstantExpression: case EvalInfo::EM_PotentialConstantExpression: case EvalInfo::EM_ConstantFold: case EvalInfo::EM_EvaluateForOverflow: case EvalInfo::EM_IgnoreSideEffects: case EvalInfo::EM_OffsetFold: // Leave it to IR generation. return Error(E); case EvalInfo::EM_ConstantExpressionUnevaluated: case EvalInfo::EM_PotentialConstantExpressionUnevaluated: // Reduce it to a constant now. return Success((Type & 2) ? 0 : -1, E); } llvm_unreachable("unexpected EvalMode"); } case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; return Success(Val.byteSwap(), E); } case Builtin::BI__builtin_classify_type: return Success(EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E); // FIXME: BI__builtin_clrsb // FIXME: BI__builtin_clrsbl // FIXME: BI__builtin_clrsbll case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: case Builtin::BI__builtin_clzll: case Builtin::BI__builtin_clzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; if (!Val) return Error(E); return Success(Val.countLeadingZeros(), E); } case Builtin::BI__builtin_constant_p: return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: case Builtin::BI__builtin_ctzs: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; if (!Val) return Error(E); return Success(Val.countTrailingZeros(), E); } case Builtin::BI__builtin_eh_return_data_regno: { int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue(); Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand); return Success(Operand, E); } case Builtin::BI__builtin_expect: return Visit(E->getArg(0)); case Builtin::BI__builtin_ffs: case Builtin::BI__builtin_ffsl: case Builtin::BI__builtin_ffsll: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; unsigned N = Val.countTrailingZeros(); return Success(N == Val.getBitWidth() ? 0 : N + 1, E); } case Builtin::BI__builtin_fpclassify: { APFloat Val(0.0); if (!EvaluateFloat(E->getArg(5), Val, Info)) return false; unsigned Arg; switch (Val.getCategory()) { case APFloat::fcNaN: Arg = 0; break; case APFloat::fcInfinity: Arg = 1; break; case APFloat::fcNormal: Arg = Val.isDenormal() ? 3 : 2; break; case APFloat::fcZero: Arg = 4; break; } return Visit(E->getArg(Arg)); } case Builtin::BI__builtin_isinf_sign: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isInfinity() ? (Val.isNegative() ? -1 : 1) : 0, E); } case Builtin::BI__builtin_isinf: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isInfinity() ? 1 : 0, E); } case Builtin::BI__builtin_isfinite: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isFinite() ? 1 : 0, E); } case Builtin::BI__builtin_isnan: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isNaN() ? 1 : 0, E); } case Builtin::BI__builtin_isnormal: { APFloat Val(0.0); return EvaluateFloat(E->getArg(0), Val, Info) && Success(Val.isNormal() ? 1 : 0, E); } case Builtin::BI__builtin_parity: case Builtin::BI__builtin_parityl: case Builtin::BI__builtin_parityll: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; return Success(Val.countPopulation() % 2, E); } case Builtin::BI__builtin_popcount: case Builtin::BI__builtin_popcountl: case Builtin::BI__builtin_popcountll: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; return Success(Val.countPopulation(), E); } case Builtin::BIstrlen: case Builtin::BIwcslen: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); // Fall through. case Builtin::BI__builtin_strlen: case Builtin::BI__builtin_wcslen: { // As an extension, we support __builtin_strlen() as a constant expression, // and support folding strlen() to a constant. LValue String; if (!EvaluatePointer(E->getArg(0), String, Info)) return false; QualType CharTy = E->getArg(0)->getType()->getPointeeType(); // Fast path: if it's a string literal, search the string value. if (const StringLiteral *S = dyn_cast_or_null( String.getLValueBase().dyn_cast())) { // The string literal may have embedded null characters. Find the first // one and truncate there. StringRef Str = S->getBytes(); int64_t Off = String.Offset.getQuantity(); if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() && S->getCharByteWidth() == 1 && // FIXME: Add fast-path for wchar_t too. Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) { Str = Str.substr(Off); StringRef::size_type Pos = Str.find(0); if (Pos != StringRef::npos) Str = Str.substr(0, Pos); return Success(Str.size(), E); } // Fall through to slow path to issue appropriate diagnostic. } // Slow path: scan the bytes of the string looking for the terminating 0. for (uint64_t Strlen = 0; /**/; ++Strlen) { APValue Char; if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) || !Char.isInt()) return false; if (!Char.getInt()) return Success(Strlen, E); if (!HandleLValueArrayAdjustment(Info, E, String, CharTy, 1)) return false; } } case Builtin::BIstrcmp: case Builtin::BIwcscmp: case Builtin::BIstrncmp: case Builtin::BIwcsncmp: case Builtin::BImemcmp: case Builtin::BIwmemcmp: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'"); else Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); // Fall through. case Builtin::BI__builtin_strcmp: case Builtin::BI__builtin_wcscmp: case Builtin::BI__builtin_strncmp: case Builtin::BI__builtin_wcsncmp: case Builtin::BI__builtin_memcmp: case Builtin::BI__builtin_wmemcmp: { LValue String1, String2; if (!EvaluatePointer(E->getArg(0), String1, Info) || !EvaluatePointer(E->getArg(1), String2, Info)) return false; QualType CharTy = E->getArg(0)->getType()->getPointeeType(); uint64_t MaxLength = uint64_t(-1); if (BuiltinOp != Builtin::BIstrcmp && BuiltinOp != Builtin::BIwcscmp && BuiltinOp != Builtin::BI__builtin_strcmp && BuiltinOp != Builtin::BI__builtin_wcscmp) { APSInt N; if (!EvaluateInteger(E->getArg(2), N, Info)) return false; MaxLength = N.getExtValue(); } bool StopAtNull = (BuiltinOp != Builtin::BImemcmp && BuiltinOp != Builtin::BIwmemcmp && BuiltinOp != Builtin::BI__builtin_memcmp && BuiltinOp != Builtin::BI__builtin_wmemcmp); for (; MaxLength; --MaxLength) { APValue Char1, Char2; if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) || !handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) || !Char1.isInt() || !Char2.isInt()) return false; if (Char1.getInt() != Char2.getInt()) return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E); if (StopAtNull && !Char1.getInt()) return Success(0, E); assert(!(StopAtNull && !Char2.getInt())); if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) || !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1)) return false; } // We hit the strncmp / memcmp limit. return Success(0, E); } case Builtin::BI__atomic_always_lock_free: case Builtin::BI__atomic_is_lock_free: case Builtin::BI__c11_atomic_is_lock_free: { APSInt SizeVal; if (!EvaluateInteger(E->getArg(0), SizeVal, Info)) return false; // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power // of two less than the maximum inline atomic width, we know it is // lock-free. If the size isn't a power of two, or greater than the // maximum alignment where we promote atomics, we know it is not lock-free // (at least not in the sense of atomic_is_lock_free). Otherwise, // the answer can only be determined at runtime; for example, 16-byte // atomics have lock-free implementations on some, but not all, // x86-64 processors. // Check power-of-two. CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue()); if (Size.isPowerOfTwo()) { // Check against inlining width. unsigned InlineWidthBits = Info.Ctx.getTargetInfo().getMaxAtomicInlineWidth(); if (Size <= Info.Ctx.toCharUnitsFromBits(InlineWidthBits)) { if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free || Size == CharUnits::One() || E->getArg(1)->isNullPointerConstant(Info.Ctx, Expr::NPC_NeverValueDependent)) // OK, we will inline appropriately-aligned operations of this size, // and _Atomic(T) is appropriately-aligned. return Success(1, E); QualType PointeeType = E->getArg(1)->IgnoreImpCasts()->getType()-> castAs()->getPointeeType(); if (!PointeeType->isIncompleteType() && Info.Ctx.getTypeAlignInChars(PointeeType) >= Size) { // OK, we will inline operations on this object. return Success(1, E); } } } return BuiltinOp == Builtin::BI__atomic_always_lock_free ? Success(0, E) : Error(E); } } } static bool HasSameBase(const LValue &A, const LValue &B) { if (!A.getLValueBase()) return !B.getLValueBase(); if (!B.getLValueBase()) return false; if (A.getLValueBase().getOpaqueValue() != B.getLValueBase().getOpaqueValue()) { const Decl *ADecl = GetLValueBaseDecl(A); if (!ADecl) return false; const Decl *BDecl = GetLValueBaseDecl(B); if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl()) return false; } return IsGlobalLValue(A.getLValueBase()) || A.getLValueCallIndex() == B.getLValueCallIndex(); } /// \brief Determine whether this is a pointer past the end of the complete /// object referred to by the lvalue. static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, const LValue &LV) { // A null pointer can be viewed as being "past the end" but we don't // choose to look at it that way here. if (!LV.getLValueBase()) return false; // If the designator is valid and refers to a subobject, we're not pointing // past the end. if (!LV.getLValueDesignator().Invalid && !LV.getLValueDesignator().isOnePastTheEnd()) return false; // A pointer to an incomplete type might be past-the-end if the type's size is // zero. We cannot tell because the type is incomplete. QualType Ty = getType(LV.getLValueBase()); if (Ty->isIncompleteType()) return true; // We're a past-the-end pointer if we point to the byte after the object, // no matter what our type or path is. auto Size = Ctx.getTypeSizeInChars(Ty); return LV.getLValueOffset() == Size; } namespace { /// \brief Data recursive integer evaluator of certain binary operators. /// /// We use a data recursive algorithm for binary operators so that we are able /// to handle extreme cases of chained binary operators without causing stack /// overflow. class DataRecursiveIntBinOpEvaluator { struct EvalResult { APValue Val; bool Failed; EvalResult() : Failed(false) { } void swap(EvalResult &RHS) { Val.swap(RHS.Val); Failed = RHS.Failed; RHS.Failed = false; } }; struct Job { const Expr *E; EvalResult LHSResult; // meaningful only for binary operator expression. enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind; Job() = default; Job(Job &&) = default; void startSpeculativeEval(EvalInfo &Info) { SpecEvalRAII = SpeculativeEvaluationRAII(Info); } private: SpeculativeEvaluationRAII SpecEvalRAII; }; SmallVector Queue; IntExprEvaluator &IntEval; EvalInfo &Info; APValue &FinalResult; public: DataRecursiveIntBinOpEvaluator(IntExprEvaluator &IntEval, APValue &Result) : IntEval(IntEval), Info(IntEval.getEvalInfo()), FinalResult(Result) { } /// \brief True if \param E is a binary operator that we are going to handle /// data recursively. /// We handle binary operators that are comma, logical, or that have operands /// with integral or enumeration type. static bool shouldEnqueue(const BinaryOperator *E) { return E->getOpcode() == BO_Comma || E->isLogicalOp() || (E->isRValue() && E->getType()->isIntegralOrEnumerationType() && E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); } bool Traverse(const BinaryOperator *E) { enqueue(E); EvalResult PrevResult; while (!Queue.empty()) process(PrevResult); if (PrevResult.Failed) return false; FinalResult.swap(PrevResult.Val); return true; } private: bool Success(uint64_t Value, const Expr *E, APValue &Result) { return IntEval.Success(Value, E, Result); } bool Success(const APSInt &Value, const Expr *E, APValue &Result) { return IntEval.Success(Value, E, Result); } bool Error(const Expr *E) { return IntEval.Error(E); } bool Error(const Expr *E, diag::kind D) { return IntEval.Error(E, D); } OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { return Info.CCEDiag(E, D); } // \brief Returns true if visiting the RHS is necessary, false otherwise. bool VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, bool &SuppressRHSDiags); bool VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, const BinaryOperator *E, APValue &Result); void EvaluateExpr(const Expr *E, EvalResult &Result) { Result.Failed = !Evaluate(Result.Val, Info, E); if (Result.Failed) Result.Val = APValue(); } void process(EvalResult &Result); void enqueue(const Expr *E) { E = E->IgnoreParens(); Queue.resize(Queue.size()+1); Queue.back().E = E; Queue.back().Kind = Job::AnyExprKind; } }; } bool DataRecursiveIntBinOpEvaluator:: VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E, bool &SuppressRHSDiags) { if (E->getOpcode() == BO_Comma) { // Ignore LHS but note if we could not evaluate it. if (LHSResult.Failed) return Info.noteSideEffect(); return true; } if (E->isLogicalOp()) { bool LHSAsBool; if (!LHSResult.Failed && HandleConversionToBool(LHSResult.Val, LHSAsBool)) { // We were able to evaluate the LHS, see if we can get away with not // evaluating the RHS: 0 && X -> 0, 1 || X -> 1 if (LHSAsBool == (E->getOpcode() == BO_LOr)) { Success(LHSAsBool, E, LHSResult.Val); return false; // Ignore RHS } } else { LHSResult.Failed = true; // Since we weren't able to evaluate the left hand side, it // might have had side effects. if (!Info.noteSideEffect()) return false; // We can't evaluate the LHS; however, sometimes the result // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. // Don't ignore RHS and suppress diagnostics from this arm. SuppressRHSDiags = true; } return true; } assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); if (LHSResult.Failed && !Info.noteFailure()) return false; // Ignore RHS; return true; } bool DataRecursiveIntBinOpEvaluator:: VisitBinOp(const EvalResult &LHSResult, const EvalResult &RHSResult, const BinaryOperator *E, APValue &Result) { if (E->getOpcode() == BO_Comma) { if (RHSResult.Failed) return false; Result = RHSResult.Val; return true; } if (E->isLogicalOp()) { bool lhsResult, rhsResult; bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult); bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult); if (LHSIsOK) { if (RHSIsOK) { if (E->getOpcode() == BO_LOr) return Success(lhsResult || rhsResult, E, Result); else return Success(lhsResult && rhsResult, E, Result); } } else { if (RHSIsOK) { // We can't evaluate the LHS; however, sometimes the result // is determined by the RHS: X && 0 -> 0, X || 1 -> 1. if (rhsResult == (E->getOpcode() == BO_LOr)) return Success(rhsResult, E, Result); } } return false; } assert(E->getLHS()->getType()->isIntegralOrEnumerationType() && E->getRHS()->getType()->isIntegralOrEnumerationType()); if (LHSResult.Failed || RHSResult.Failed) return false; const APValue &LHSVal = LHSResult.Val; const APValue &RHSVal = RHSResult.Val; // Handle cases like (unsigned long)&a + 4. if (E->isAdditiveOp() && LHSVal.isLValue() && RHSVal.isInt()) { Result = LHSVal; CharUnits AdditionalOffset = CharUnits::fromQuantity(RHSVal.getInt().getZExtValue()); if (E->getOpcode() == BO_Add) Result.getLValueOffset() += AdditionalOffset; else Result.getLValueOffset() -= AdditionalOffset; return true; } // Handle cases like 4 + (unsigned long)&a if (E->getOpcode() == BO_Add && RHSVal.isLValue() && LHSVal.isInt()) { Result = RHSVal; Result.getLValueOffset() += CharUnits::fromQuantity(LHSVal.getInt().getZExtValue()); return true; } if (E->getOpcode() == BO_Sub && LHSVal.isLValue() && RHSVal.isLValue()) { // Handle (intptr_t)&&A - (intptr_t)&&B. if (!LHSVal.getLValueOffset().isZero() || !RHSVal.getLValueOffset().isZero()) return false; const Expr *LHSExpr = LHSVal.getLValueBase().dyn_cast(); const Expr *RHSExpr = RHSVal.getLValueBase().dyn_cast(); if (!LHSExpr || !RHSExpr) return false; const AddrLabelExpr *LHSAddrExpr = dyn_cast(LHSExpr); const AddrLabelExpr *RHSAddrExpr = dyn_cast(RHSExpr); if (!LHSAddrExpr || !RHSAddrExpr) return false; // Make sure both labels come from the same function. if (LHSAddrExpr->getLabel()->getDeclContext() != RHSAddrExpr->getLabel()->getDeclContext()) return false; Result = APValue(LHSAddrExpr, RHSAddrExpr); return true; } // All the remaining cases expect both operands to be an integer if (!LHSVal.isInt() || !RHSVal.isInt()) return Error(E); // Set up the width and signedness manually, in case it can't be deduced // from the operation we're performing. // FIXME: Don't do this in the cases where we can deduce it. APSInt Value(Info.Ctx.getIntWidth(E->getType()), E->getType()->isUnsignedIntegerOrEnumerationType()); if (!handleIntIntBinOp(Info, E, LHSVal.getInt(), E->getOpcode(), RHSVal.getInt(), Value)) return false; return Success(Value, E, Result); } void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) { Job &job = Queue.back(); switch (job.Kind) { case Job::AnyExprKind: { if (const BinaryOperator *Bop = dyn_cast(job.E)) { if (shouldEnqueue(Bop)) { job.Kind = Job::BinOpKind; enqueue(Bop->getLHS()); return; } } EvaluateExpr(job.E, Result); Queue.pop_back(); return; } case Job::BinOpKind: { const BinaryOperator *Bop = cast(job.E); bool SuppressRHSDiags = false; if (!VisitBinOpLHSOnly(Result, Bop, SuppressRHSDiags)) { Queue.pop_back(); return; } if (SuppressRHSDiags) job.startSpeculativeEval(Info); job.LHSResult.swap(Result); job.Kind = Job::BinOpVisitedLHSKind; enqueue(Bop->getRHS()); return; } case Job::BinOpVisitedLHSKind: { const BinaryOperator *Bop = cast(job.E); EvalResult RHS; RHS.swap(Result); Result.Failed = !VisitBinOp(job.LHSResult, RHS, Bop, Result.Val); Queue.pop_back(); return; } } llvm_unreachable("Invalid Job::Kind!"); } namespace { /// Used when we determine that we should fail, but can keep evaluating prior to /// noting that we had a failure. class DelayedNoteFailureRAII { EvalInfo &Info; bool NoteFailure; public: DelayedNoteFailureRAII(EvalInfo &Info, bool NoteFailure = true) : Info(Info), NoteFailure(NoteFailure) {} ~DelayedNoteFailureRAII() { if (NoteFailure) { bool ContinueAfterFailure = Info.noteFailure(); (void)ContinueAfterFailure; assert(ContinueAfterFailure && "Shouldn't have kept evaluating on failure."); } } }; } bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // We don't call noteFailure immediately because the assignment happens after // we evaluate LHS and RHS. if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp()) return Error(E); DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp()); if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E)) return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E); QualType LHSTy = E->getLHS()->getType(); QualType RHSTy = E->getRHS()->getType(); if (LHSTy->isAnyComplexType() || RHSTy->isAnyComplexType()) { ComplexValue LHS, RHS; bool LHSOK; if (E->isAssignmentOp()) { LValue LV; EvaluateLValue(E->getLHS(), LV, Info); LHSOK = false; } else if (LHSTy->isRealFloatingType()) { LHSOK = EvaluateFloat(E->getLHS(), LHS.FloatReal, Info); if (LHSOK) { LHS.makeComplexFloat(); LHS.FloatImag = APFloat(LHS.FloatReal.getSemantics()); } } else { LHSOK = EvaluateComplex(E->getLHS(), LHS, Info); } if (!LHSOK && !Info.noteFailure()) return false; if (E->getRHS()->getType()->isRealFloatingType()) { if (!EvaluateFloat(E->getRHS(), RHS.FloatReal, Info) || !LHSOK) return false; RHS.makeComplexFloat(); RHS.FloatImag = APFloat(RHS.FloatReal.getSemantics()); } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; if (LHS.isComplexFloat()) { APFloat::cmpResult CR_r = LHS.getComplexFloatReal().compare(RHS.getComplexFloatReal()); APFloat::cmpResult CR_i = LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag()); if (E->getOpcode() == BO_EQ) return Success((CR_r == APFloat::cmpEqual && CR_i == APFloat::cmpEqual), E); else { assert(E->getOpcode() == BO_NE && "Invalid complex comparison."); return Success(((CR_r == APFloat::cmpGreaterThan || CR_r == APFloat::cmpLessThan || CR_r == APFloat::cmpUnordered) || (CR_i == APFloat::cmpGreaterThan || CR_i == APFloat::cmpLessThan || CR_i == APFloat::cmpUnordered)), E); } } else { if (E->getOpcode() == BO_EQ) return Success((LHS.getComplexIntReal() == RHS.getComplexIntReal() && LHS.getComplexIntImag() == RHS.getComplexIntImag()), E); else { assert(E->getOpcode() == BO_NE && "Invalid compex comparison."); return Success((LHS.getComplexIntReal() != RHS.getComplexIntReal() || LHS.getComplexIntImag() != RHS.getComplexIntImag()), E); } } } if (LHSTy->isRealFloatingType() && RHSTy->isRealFloatingType()) { APFloat RHS(0.0), LHS(0.0); bool LHSOK = EvaluateFloat(E->getRHS(), RHS, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluateFloat(E->getLHS(), LHS, Info) || !LHSOK) return false; APFloat::cmpResult CR = LHS.compare(RHS); switch (E->getOpcode()) { default: llvm_unreachable("Invalid binary operator!"); case BO_LT: return Success(CR == APFloat::cmpLessThan, E); case BO_GT: return Success(CR == APFloat::cmpGreaterThan, E); case BO_LE: return Success(CR == APFloat::cmpLessThan || CR == APFloat::cmpEqual, E); case BO_GE: return Success(CR == APFloat::cmpGreaterThan || CR == APFloat::cmpEqual, E); case BO_EQ: return Success(CR == APFloat::cmpEqual, E); case BO_NE: return Success(CR == APFloat::cmpGreaterThan || CR == APFloat::cmpLessThan || CR == APFloat::cmpUnordered, E); } } if (LHSTy->isPointerType() && RHSTy->isPointerType()) { if (E->getOpcode() == BO_Sub || E->isComparisonOp()) { LValue LHSValue, RHSValue; bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK) return false; // Reject differing bases from the normal codepath; we special-case // comparisons to null. if (!HasSameBase(LHSValue, RHSValue)) { if (E->getOpcode() == BO_Sub) { // Handle &&A - &&B. if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero()) return Error(E); const Expr *LHSExpr = LHSValue.Base.dyn_cast(); const Expr *RHSExpr = RHSValue.Base.dyn_cast(); if (!LHSExpr || !RHSExpr) return Error(E); const AddrLabelExpr *LHSAddrExpr = dyn_cast(LHSExpr); const AddrLabelExpr *RHSAddrExpr = dyn_cast(RHSExpr); if (!LHSAddrExpr || !RHSAddrExpr) return Error(E); // Make sure both labels come from the same function. if (LHSAddrExpr->getLabel()->getDeclContext() != RHSAddrExpr->getLabel()->getDeclContext()) return Error(E); return Success(APValue(LHSAddrExpr, RHSAddrExpr), E); } // Inequalities and subtractions between unrelated pointers have // unspecified or undefined behavior. if (!E->isEqualityOp()) return Error(E); // A constant address may compare equal to the address of a symbol. // The one exception is that address of an object cannot compare equal // to a null pointer constant. if ((!LHSValue.Base && !LHSValue.Offset.isZero()) || (!RHSValue.Base && !RHSValue.Offset.isZero())) return Error(E); // It's implementation-defined whether distinct literals will have // distinct addresses. In clang, the result of such a comparison is // unspecified, so it is not a constant expression. However, we do know // that the address of a literal will be non-null. if ((IsLiteralLValue(LHSValue) || IsLiteralLValue(RHSValue)) && LHSValue.Base && RHSValue.Base) return Error(E); // We can't tell whether weak symbols will end up pointing to the same // object. if (IsWeakLValue(LHSValue) || IsWeakLValue(RHSValue)) return Error(E); // We can't compare the address of the start of one object with the // past-the-end address of another object, per C++ DR1652. if ((LHSValue.Base && LHSValue.Offset.isZero() && isOnePastTheEndOfCompleteObject(Info.Ctx, RHSValue)) || (RHSValue.Base && RHSValue.Offset.isZero() && isOnePastTheEndOfCompleteObject(Info.Ctx, LHSValue))) return Error(E); // We can't tell whether an object is at the same address as another // zero sized object. if ((RHSValue.Base && isZeroSized(LHSValue)) || (LHSValue.Base && isZeroSized(RHSValue))) return Error(E); // Pointers with different bases cannot represent the same object. // (Note that clang defaults to -fmerge-all-constants, which can // lead to inconsistent results for comparisons involving the address // of a constant; this generally doesn't matter in practice.) return Success(E->getOpcode() == BO_NE, E); } const CharUnits &LHSOffset = LHSValue.getLValueOffset(); const CharUnits &RHSOffset = RHSValue.getLValueOffset(); SubobjectDesignator &LHSDesignator = LHSValue.getLValueDesignator(); SubobjectDesignator &RHSDesignator = RHSValue.getLValueDesignator(); if (E->getOpcode() == BO_Sub) { // C++11 [expr.add]p6: // Unless both pointers point to elements of the same array object, or // one past the last element of the array object, the behavior is // undefined. if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && !AreElementsOfSameArray(getType(LHSValue.Base), LHSDesignator, RHSDesignator)) CCEDiag(E, diag::note_constexpr_pointer_subtraction_not_same_array); QualType Type = E->getLHS()->getType(); QualType ElementType = Type->getAs()->getPointeeType(); CharUnits ElementSize; if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize)) return false; // As an extension, a type may have zero size (empty struct or union in // C, array of zero length). Pointer subtraction in such cases has // undefined behavior, so is not constant. if (ElementSize.isZero()) { Info.FFDiag(E, diag::note_constexpr_pointer_subtraction_zero_size) << ElementType; return false; } // FIXME: LLVM and GCC both compute LHSOffset - RHSOffset at runtime, // and produce incorrect results when it overflows. Such behavior // appears to be non-conforming, but is common, so perhaps we should // assume the standard intended for such cases to be undefined behavior // and check for them. // Compute (LHSOffset - RHSOffset) / Size carefully, checking for // overflow in the final conversion to ptrdiff_t. APSInt LHS( llvm::APInt(65, (int64_t)LHSOffset.getQuantity(), true), false); APSInt RHS( llvm::APInt(65, (int64_t)RHSOffset.getQuantity(), true), false); APSInt ElemSize( llvm::APInt(65, (int64_t)ElementSize.getQuantity(), true), false); APSInt TrueResult = (LHS - RHS) / ElemSize; APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E->getType())); if (Result.extend(65) != TrueResult && !HandleOverflow(Info, E, TrueResult, E->getType())) return false; return Success(Result, E); } // C++11 [expr.rel]p3: // Pointers to void (after pointer conversions) can be compared, with a // result defined as follows: If both pointers represent the same // address or are both the null pointer value, the result is true if the // operator is <= or >= and false otherwise; otherwise the result is // unspecified. // We interpret this as applying to pointers to *cv* void. if (LHSTy->isVoidPointerType() && LHSOffset != RHSOffset && E->isRelationalOp()) CCEDiag(E, diag::note_constexpr_void_comparison); // C++11 [expr.rel]p2: // - If two pointers point to non-static data members of the same object, // or to subobjects or array elements fo such members, recursively, the // pointer to the later declared member compares greater provided the // two members have the same access control and provided their class is // not a union. // [...] // - Otherwise pointer comparisons are unspecified. if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && E->isRelationalOp()) { bool WasArrayIndex; unsigned Mismatch = FindDesignatorMismatch(getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex); // At the point where the designators diverge, the comparison has a // specified value if: // - we are comparing array indices // - we are comparing fields of a union, or fields with the same access // Otherwise, the result is unspecified and thus the comparison is not a // constant expression. if (!WasArrayIndex && Mismatch < LHSDesignator.Entries.size() && Mismatch < RHSDesignator.Entries.size()) { const FieldDecl *LF = getAsField(LHSDesignator.Entries[Mismatch]); const FieldDecl *RF = getAsField(RHSDesignator.Entries[Mismatch]); if (!LF && !RF) CCEDiag(E, diag::note_constexpr_pointer_comparison_base_classes); else if (!LF) CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) << getAsBaseClass(LHSDesignator.Entries[Mismatch]) << RF->getParent() << RF; else if (!RF) CCEDiag(E, diag::note_constexpr_pointer_comparison_base_field) << getAsBaseClass(RHSDesignator.Entries[Mismatch]) << LF->getParent() << LF; else if (!LF->getParent()->isUnion() && LF->getAccess() != RF->getAccess()) CCEDiag(E, diag::note_constexpr_pointer_comparison_differing_access) << LF << LF->getAccess() << RF << RF->getAccess() << LF->getParent(); } } // The comparison here must be unsigned, and performed with the same // width as the pointer. unsigned PtrSize = Info.Ctx.getTypeSize(LHSTy); uint64_t CompareLHS = LHSOffset.getQuantity(); uint64_t CompareRHS = RHSOffset.getQuantity(); assert(PtrSize <= 64 && "Unexpected pointer width"); uint64_t Mask = ~0ULL >> (64 - PtrSize); CompareLHS &= Mask; CompareRHS &= Mask; // If there is a base and this is a relational operator, we can only // compare pointers within the object in question; otherwise, the result // depends on where the object is located in memory. if (!LHSValue.Base.isNull() && E->isRelationalOp()) { QualType BaseTy = getType(LHSValue.Base); if (BaseTy->isIncompleteType()) return Error(E); CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy); uint64_t OffsetLimit = Size.getQuantity(); if (CompareLHS > OffsetLimit || CompareRHS > OffsetLimit) return Error(E); } switch (E->getOpcode()) { default: llvm_unreachable("missing comparison operator"); case BO_LT: return Success(CompareLHS < CompareRHS, E); case BO_GT: return Success(CompareLHS > CompareRHS, E); case BO_LE: return Success(CompareLHS <= CompareRHS, E); case BO_GE: return Success(CompareLHS >= CompareRHS, E); case BO_EQ: return Success(CompareLHS == CompareRHS, E); case BO_NE: return Success(CompareLHS != CompareRHS, E); } } } if (LHSTy->isMemberPointerType()) { assert(E->isEqualityOp() && "unexpected member pointer operation"); assert(RHSTy->isMemberPointerType() && "invalid comparison"); MemberPtr LHSValue, RHSValue; bool LHSOK = EvaluateMemberPointer(E->getLHS(), LHSValue, Info); if (!LHSOK && !Info.noteFailure()) return false; if (!EvaluateMemberPointer(E->getRHS(), RHSValue, Info) || !LHSOK) return false; // C++11 [expr.eq]p2: // If both operands are null, they compare equal. Otherwise if only one is // null, they compare unequal. if (!LHSValue.getDecl() || !RHSValue.getDecl()) { bool Equal = !LHSValue.getDecl() && !RHSValue.getDecl(); return Success(E->getOpcode() == BO_EQ ? Equal : !Equal, E); } // Otherwise if either is a pointer to a virtual member function, the // result is unspecified. if (const CXXMethodDecl *MD = dyn_cast(LHSValue.getDecl())) if (MD->isVirtual()) CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; if (const CXXMethodDecl *MD = dyn_cast(RHSValue.getDecl())) if (MD->isVirtual()) CCEDiag(E, diag::note_constexpr_compare_virtual_mem_ptr) << MD; // Otherwise they compare equal if and only if they would refer to the // same member of the same most derived object or the same subobject if // they were dereferenced with a hypothetical object of the associated // class type. bool Equal = LHSValue == RHSValue; return Success(E->getOpcode() == BO_EQ ? Equal : !Equal, E); } if (LHSTy->isNullPtrType()) { assert(E->isComparisonOp() && "unexpected nullptr operation"); assert(RHSTy->isNullPtrType() && "missing pointer conversion"); // C++11 [expr.rel]p4, [expr.eq]p3: If two operands of type std::nullptr_t // are compared, the result is true of the operator is <=, >= or ==, and // false otherwise. BinaryOperator::Opcode Opcode = E->getOpcode(); return Success(Opcode == BO_EQ || Opcode == BO_LE || Opcode == BO_GE, E); } assert((!LHSTy->isIntegralOrEnumerationType() || !RHSTy->isIntegralOrEnumerationType()) && "DataRecursiveIntBinOpEvaluator should have handled integral types"); // We can't continue from here for non-integral types. return ExprEvaluatorBaseTy::VisitBinaryOperator(E); } /// VisitUnaryExprOrTypeTraitExpr - Evaluate a sizeof, alignof or vec_step with /// a result as the expression's type. bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr *E) { switch(E->getKind()) { case UETT_AlignOf: { if (E->isArgumentType()) return Success(GetAlignOfType(Info, E->getArgumentType()), E); else return Success(GetAlignOfExpr(Info, E->getArgumentExpr()), E); } case UETT_VecStep: { QualType Ty = E->getTypeOfArgument(); if (Ty->isVectorType()) { unsigned n = Ty->castAs()->getNumElements(); // The vec_step built-in functions that take a 3-component // vector return 4. (OpenCL 1.1 spec 6.11.12) if (n == 3) n = 4; return Success(n, E); } else return Success(1, E); } case UETT_SizeOf: { QualType SrcTy = E->getTypeOfArgument(); // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, // the result is the size of the referenced type." if (const ReferenceType *Ref = SrcTy->getAs()) SrcTy = Ref->getPointeeType(); CharUnits Sizeof; if (!HandleSizeof(Info, E->getExprLoc(), SrcTy, Sizeof)) return false; return Success(Sizeof, E); } case UETT_OpenMPRequiredSimdAlign: assert(E->isArgumentType()); return Success( Info.Ctx.toCharUnitsFromBits( Info.Ctx.getOpenMPDefaultSimdAlign(E->getArgumentType())) .getQuantity(), E); } llvm_unreachable("unknown expr/type trait"); } bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { CharUnits Result; unsigned n = OOE->getNumComponents(); if (n == 0) return Error(OOE); QualType CurrentType = OOE->getTypeSourceInfo()->getType(); for (unsigned i = 0; i != n; ++i) { OffsetOfNode ON = OOE->getComponent(i); switch (ON.getKind()) { case OffsetOfNode::Array: { const Expr *Idx = OOE->getIndexExpr(ON.getArrayExprIndex()); APSInt IdxResult; if (!EvaluateInteger(Idx, IdxResult, Info)) return false; const ArrayType *AT = Info.Ctx.getAsArrayType(CurrentType); if (!AT) return Error(OOE); CurrentType = AT->getElementType(); CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(CurrentType); Result += IdxResult.getSExtValue() * ElementSize; break; } case OffsetOfNode::Field: { FieldDecl *MemberDecl = ON.getField(); const RecordType *RT = CurrentType->getAs(); if (!RT) return Error(OOE); RecordDecl *RD = RT->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); unsigned i = MemberDecl->getFieldIndex(); assert(i < RL.getFieldCount() && "offsetof field in wrong type"); Result += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i)); CurrentType = MemberDecl->getType().getNonReferenceType(); break; } case OffsetOfNode::Identifier: llvm_unreachable("dependent __builtin_offsetof"); case OffsetOfNode::Base: { CXXBaseSpecifier *BaseSpec = ON.getBase(); if (BaseSpec->isVirtual()) return Error(OOE); // Find the layout of the class whose base we are looking into. const RecordType *RT = CurrentType->getAs(); if (!RT) return Error(OOE); RecordDecl *RD = RT->getDecl(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); // Find the base class itself. CurrentType = BaseSpec->getType(); const RecordType *BaseRT = CurrentType->getAs(); if (!BaseRT) return Error(OOE); // Add the offset to the base. Result += RL.getBaseClassOffset(cast(BaseRT->getDecl())); break; } } } return Success(Result, OOE); } bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { switch (E->getOpcode()) { default: // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. // See C99 6.6p3. return Error(E); case UO_Extension: // FIXME: Should extension allow i-c-e extension expressions in its scope? // If so, we could clear the diagnostic ID. return Visit(E->getSubExpr()); case UO_Plus: // The result is just the value. return Visit(E->getSubExpr()); case UO_Minus: { if (!Visit(E->getSubExpr())) return false; if (!Result.isInt()) return Error(E); const APSInt &Value = Result.getInt(); if (Value.isSigned() && Value.isMinSignedValue() && !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1), E->getType())) return false; return Success(-Value, E); } case UO_Not: { if (!Visit(E->getSubExpr())) return false; if (!Result.isInt()) return Error(E); return Success(~Result.getInt(), E); } case UO_LNot: { bool bres; if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info)) return false; return Success(!bres, E); } } } /// HandleCast - This is used to evaluate implicit or explicit casts where the /// result type is integer. bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { const Expr *SubExpr = E->getSubExpr(); QualType DestType = E->getType(); QualType SrcType = SubExpr->getType(); switch (E->getCastKind()) { case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToPointer: case CK_NullToMemberPointer: case CK_BaseToDerivedMemberPointer: case CK_DerivedToBaseMemberPointer: case CK_ReinterpretMemberPointer: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_ToVoid: case CK_VectorSplat: case CK_IntegralToFloating: case CK_FloatingCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingRealToComplex: case CK_FloatingComplexToReal: case CK_FloatingComplexCast: case CK_FloatingComplexToIntegralComplex: case CK_IntegralRealToComplex: case CK_IntegralComplexCast: case CK_IntegralComplexToFloatingComplex: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: case CK_Dependent: case CK_LValueBitCast: case CK_ARCProduceObject: case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: return Error(E); case CK_UserDefinedConversion: case CK_LValueToRValue: case CK_AtomicToNonAtomic: case CK_NoOp: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_MemberPointerToBoolean: case CK_PointerToBoolean: case CK_IntegralToBoolean: case CK_FloatingToBoolean: case CK_BooleanToSignedIntegral: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToBoolean: { bool BoolResult; if (!EvaluateAsBooleanCondition(SubExpr, BoolResult, Info)) return false; uint64_t IntResult = BoolResult; if (BoolResult && E->getCastKind() == CK_BooleanToSignedIntegral) IntResult = (uint64_t)-1; return Success(IntResult, E); } case CK_IntegralCast: { if (!Visit(SubExpr)) return false; if (!Result.isInt()) { // Allow casts of address-of-label differences if they are no-ops // or narrowing. (The narrowing case isn't actually guaranteed to // be constant-evaluatable except in some narrow cases which are hard // to detect here. We let it through on the assumption the user knows // what they are doing.) if (Result.isAddrLabelDiff()) return Info.Ctx.getTypeSize(DestType) <= Info.Ctx.getTypeSize(SrcType); // Only allow casts of lvalues if they are lossless. return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType); } return Success(HandleIntToIntCast(Info, E, DestType, SrcType, Result.getInt()), E); } case CK_PointerToIntegral: { CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; LValue LV; if (!EvaluatePointer(SubExpr, LV, Info)) return false; if (LV.getLValueBase()) { // Only allow based lvalue casts if they are lossless. // FIXME: Allow a larger integer size than the pointer size, and allow // narrowing back down to pointer width in subsequent integral casts. // FIXME: Check integer type's active bits, not its type size. if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType)) return Error(E); LV.Designator.setInvalid(); LV.moveInto(Result); return true; } uint64_t V; if (LV.isNullPointer()) V = Info.Ctx.getTargetNullPointerValue(SrcType); else V = LV.getLValueOffset().getQuantity(); APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType); return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } case CK_IntegralComplexToReal: { ComplexValue C; if (!EvaluateComplex(SubExpr, C, Info)) return false; return Success(C.getComplexIntReal(), E); } case CK_FloatingToIntegral: { APFloat F(0.0); if (!EvaluateFloat(SubExpr, F, Info)) return false; APSInt Value; if (!HandleFloatToIntCast(Info, E, SrcType, F, DestType, Value)) return false; return Success(Value, E); } } llvm_unreachable("unknown cast resulting in integral value"); } bool IntExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue LV; if (!EvaluateComplex(E->getSubExpr(), LV, Info)) return false; if (!LV.isComplexInt()) return Error(E); return Success(LV.getComplexIntReal(), E); } return Visit(E->getSubExpr()); } bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isComplexIntegerType()) { ComplexValue LV; if (!EvaluateComplex(E->getSubExpr(), LV, Info)) return false; if (!LV.isComplexInt()) return Error(E); return Success(LV.getComplexIntImag(), E); } VisitIgnoredValue(E->getSubExpr()); return Success(0, E); } bool IntExprEvaluator::VisitSizeOfPackExpr(const SizeOfPackExpr *E) { return Success(E->getPackLength(), E); } bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { return Success(E->getValue(), E); } //===----------------------------------------------------------------------===// // Float Evaluation //===----------------------------------------------------------------------===// namespace { class FloatExprEvaluator : public ExprEvaluatorBase { APFloat &Result; public: FloatExprEvaluator(EvalInfo &info, APFloat &result) : ExprEvaluatorBaseTy(info), Result(result) {} bool Success(const APValue &V, const Expr *e) { Result = V.getFloat(); return true; } bool ZeroInitialization(const Expr *E) { Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType())); return true; } bool VisitCallExpr(const CallExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitCastExpr(const CastExpr *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); // FIXME: Missing: array subscript of vector, member of vector }; } // end anonymous namespace static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isRealFloatingType()); return FloatExprEvaluator(Info, Result).Visit(E); } static bool TryEvaluateBuiltinNaN(const ASTContext &Context, QualType ResultTy, const Expr *Arg, bool SNaN, llvm::APFloat &Result) { const StringLiteral *S = dyn_cast(Arg->IgnoreParenCasts()); if (!S) return false; const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy); llvm::APInt fill; // Treat empty strings as if they were zero. if (S->getString().empty()) fill = llvm::APInt(32, 0); else if (S->getString().getAsInteger(0, fill)) return false; if (Context.getTargetInfo().isNan2008()) { if (SNaN) Result = llvm::APFloat::getSNaN(Sem, false, &fill); else Result = llvm::APFloat::getQNaN(Sem, false, &fill); } else { // Prior to IEEE 754-2008, architectures were allowed to choose whether // the first bit of their significand was set for qNaN or sNaN. MIPS chose // a different encoding to what became a standard in 2008, and for pre- // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as // sNaN. This is now known as "legacy NaN" encoding. if (SNaN) Result = llvm::APFloat::getQNaN(Sem, false, &fill); else Result = llvm::APFloat::getSNaN(Sem, false, &fill); } return true; } bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { switch (E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: case Builtin::BI__builtin_inf: case Builtin::BI__builtin_inff: case Builtin::BI__builtin_infl: { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); Result = llvm::APFloat::getInf(Sem); return true; } case Builtin::BI__builtin_nans: case Builtin::BI__builtin_nansf: case Builtin::BI__builtin_nansl: if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), true, Result)) return Error(E); return true; case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: // If this is __builtin_nan() turn this into a nan, otherwise we // can't constant fold it. if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), false, Result)) return Error(E); return true; case Builtin::BI__builtin_fabs: case Builtin::BI__builtin_fabsf: case Builtin::BI__builtin_fabsl: if (!EvaluateFloat(E->getArg(0), Result, Info)) return false; if (Result.isNegative()) Result.changeSign(); return true; // FIXME: Builtin::BI__builtin_powi // FIXME: Builtin::BI__builtin_powif // FIXME: Builtin::BI__builtin_powil case Builtin::BI__builtin_copysign: case Builtin::BI__builtin_copysignf: case Builtin::BI__builtin_copysignl: { APFloat RHS(0.); if (!EvaluateFloat(E->getArg(0), Result, Info) || !EvaluateFloat(E->getArg(1), RHS, Info)) return false; Result.copySign(RHS); return true; } } } bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue CV; if (!EvaluateComplex(E->getSubExpr(), CV, Info)) return false; Result = CV.FloatReal; return true; } return Visit(E->getSubExpr()); } bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue CV; if (!EvaluateComplex(E->getSubExpr(), CV, Info)) return false; Result = CV.FloatImag; return true; } VisitIgnoredValue(E->getSubExpr()); const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); Result = llvm::APFloat::getZero(Sem); return true; } bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { switch (E->getOpcode()) { default: return Error(E); case UO_Plus: return EvaluateFloat(E->getSubExpr(), Result, Info); case UO_Minus: if (!EvaluateFloat(E->getSubExpr(), Result, Info)) return false; Result.changeSign(); return true; } } bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); APFloat RHS(0.0); bool LHSOK = EvaluateFloat(E->getLHS(), Result, Info); if (!LHSOK && !Info.noteFailure()) return false; return EvaluateFloat(E->getRHS(), RHS, Info) && LHSOK && handleFloatFloatBinOp(Info, E, Result, E->getOpcode(), RHS); } bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { Result = E->getValue(); return true; } bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) { const Expr* SubExpr = E->getSubExpr(); switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_IntegralToFloating: { APSInt IntResult; return EvaluateInteger(SubExpr, IntResult, Info) && HandleIntToFloatCast(Info, E, SubExpr->getType(), IntResult, E->getType(), Result); } case CK_FloatingCast: { if (!Visit(SubExpr)) return false; return HandleFloatToFloatCast(Info, E, SubExpr->getType(), E->getType(), Result); } case CK_FloatingComplexToReal: { ComplexValue V; if (!EvaluateComplex(SubExpr, V, Info)) return false; Result = V.getComplexFloatReal(); return true; } } } //===----------------------------------------------------------------------===// // Complex Evaluation (for float and integer) //===----------------------------------------------------------------------===// namespace { class ComplexExprEvaluator : public ExprEvaluatorBase { ComplexValue &Result; public: ComplexExprEvaluator(EvalInfo &info, ComplexValue &Result) : ExprEvaluatorBaseTy(info), Result(Result) {} bool Success(const APValue &V, const Expr *e) { Result.setFrom(V); return true; } bool ZeroInitialization(const Expr *E); //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// bool VisitImaginaryLiteral(const ImaginaryLiteral *E); bool VisitCastExpr(const CastExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitInitListExpr(const InitListExpr *E); }; } // end anonymous namespace static bool EvaluateComplex(const Expr *E, ComplexValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isAnyComplexType()); return ComplexExprEvaluator(Info, Result).Visit(E); } bool ComplexExprEvaluator::ZeroInitialization(const Expr *E) { QualType ElemTy = E->getType()->castAs()->getElementType(); if (ElemTy->isRealFloatingType()) { Result.makeComplexFloat(); APFloat Zero = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy)); Result.FloatReal = Zero; Result.FloatImag = Zero; } else { Result.makeComplexInt(); APSInt Zero = Info.Ctx.MakeIntValue(0, ElemTy); Result.IntReal = Zero; Result.IntImag = Zero; } return true; } bool ComplexExprEvaluator::VisitImaginaryLiteral(const ImaginaryLiteral *E) { const Expr* SubExpr = E->getSubExpr(); if (SubExpr->getType()->isRealFloatingType()) { Result.makeComplexFloat(); APFloat &Imag = Result.FloatImag; if (!EvaluateFloat(SubExpr, Imag, Info)) return false; Result.FloatReal = APFloat(Imag.getSemantics()); return true; } else { assert(SubExpr->getType()->isIntegerType() && "Unexpected imaginary literal."); Result.makeComplexInt(); APSInt &Imag = Result.IntImag; if (!EvaluateInteger(SubExpr, Imag, Info)) return false; Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned()); return true; } } bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { case CK_BitCast: case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: case CK_Dynamic: case CK_ToUnion: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToPointer: case CK_NullToMemberPointer: case CK_BaseToDerivedMemberPointer: case CK_DerivedToBaseMemberPointer: case CK_MemberPointerToBoolean: case CK_ReinterpretMemberPointer: case CK_ConstructorConversion: case CK_IntegralToPointer: case CK_PointerToIntegral: case CK_PointerToBoolean: case CK_ToVoid: case CK_VectorSplat: case CK_IntegralCast: case CK_BooleanToSignedIntegral: case CK_IntegralToBoolean: case CK_IntegralToFloating: case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: case CK_CPointerToObjCPointerCast: case CK_BlockPointerToObjCPointerCast: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_FloatingComplexToReal: case CK_FloatingComplexToBoolean: case CK_IntegralComplexToReal: case CK_IntegralComplexToBoolean: case CK_ARCProduceObject: case CK_ARCConsumeObject: case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_ZeroToOCLQueue: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: case CK_AtomicToNonAtomic: case CK_NoOp: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_Dependent: case CK_LValueBitCast: case CK_UserDefinedConversion: return Error(E); case CK_FloatingRealToComplex: { APFloat &Real = Result.FloatReal; if (!EvaluateFloat(E->getSubExpr(), Real, Info)) return false; Result.makeComplexFloat(); Result.FloatImag = APFloat(Real.getSemantics()); return true; } case CK_FloatingComplexCast: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->getAs()->getElementType(); QualType From = E->getSubExpr()->getType()->getAs()->getElementType(); return HandleFloatToFloatCast(Info, E, From, To, Result.FloatReal) && HandleFloatToFloatCast(Info, E, From, To, Result.FloatImag); } case CK_FloatingComplexToIntegralComplex: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->getAs()->getElementType(); QualType From = E->getSubExpr()->getType()->getAs()->getElementType(); Result.makeComplexInt(); return HandleFloatToIntCast(Info, E, From, Result.FloatReal, To, Result.IntReal) && HandleFloatToIntCast(Info, E, From, Result.FloatImag, To, Result.IntImag); } case CK_IntegralRealToComplex: { APSInt &Real = Result.IntReal; if (!EvaluateInteger(E->getSubExpr(), Real, Info)) return false; Result.makeComplexInt(); Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned()); return true; } case CK_IntegralComplexCast: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->getAs()->getElementType(); QualType From = E->getSubExpr()->getType()->getAs()->getElementType(); Result.IntReal = HandleIntToIntCast(Info, E, To, From, Result.IntReal); Result.IntImag = HandleIntToIntCast(Info, E, To, From, Result.IntImag); return true; } case CK_IntegralComplexToFloatingComplex: { if (!Visit(E->getSubExpr())) return false; QualType To = E->getType()->castAs()->getElementType(); QualType From = E->getSubExpr()->getType()->castAs()->getElementType(); Result.makeComplexFloat(); return HandleIntToFloatCast(Info, E, From, Result.IntReal, To, Result.FloatReal) && HandleIntToFloatCast(Info, E, From, Result.IntImag, To, Result.FloatImag); } } llvm_unreachable("unknown cast resulting in complex value"); } bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { if (E->isPtrMemOp() || E->isAssignmentOp() || E->getOpcode() == BO_Comma) return ExprEvaluatorBaseTy::VisitBinaryOperator(E); // Track whether the LHS or RHS is real at the type system level. When this is // the case we can simplify our evaluation strategy. bool LHSReal = false, RHSReal = false; bool LHSOK; if (E->getLHS()->getType()->isRealFloatingType()) { LHSReal = true; APFloat &Real = Result.FloatReal; LHSOK = EvaluateFloat(E->getLHS(), Real, Info); if (LHSOK) { Result.makeComplexFloat(); Result.FloatImag = APFloat(Real.getSemantics()); } } else { LHSOK = Visit(E->getLHS()); } if (!LHSOK && !Info.noteFailure()) return false; ComplexValue RHS; if (E->getRHS()->getType()->isRealFloatingType()) { RHSReal = true; APFloat &Real = RHS.FloatReal; if (!EvaluateFloat(E->getRHS(), Real, Info) || !LHSOK) return false; RHS.makeComplexFloat(); RHS.FloatImag = APFloat(Real.getSemantics()); } else if (!EvaluateComplex(E->getRHS(), RHS, Info) || !LHSOK) return false; assert(!(LHSReal && RHSReal) && "Cannot have both operands of a complex operation be real."); switch (E->getOpcode()) { default: return Error(E); case BO_Add: if (Result.isComplexFloat()) { Result.getComplexFloatReal().add(RHS.getComplexFloatReal(), APFloat::rmNearestTiesToEven); if (LHSReal) Result.getComplexFloatImag() = RHS.getComplexFloatImag(); else if (!RHSReal) Result.getComplexFloatImag().add(RHS.getComplexFloatImag(), APFloat::rmNearestTiesToEven); } else { Result.getComplexIntReal() += RHS.getComplexIntReal(); Result.getComplexIntImag() += RHS.getComplexIntImag(); } break; case BO_Sub: if (Result.isComplexFloat()) { Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(), APFloat::rmNearestTiesToEven); if (LHSReal) { Result.getComplexFloatImag() = RHS.getComplexFloatImag(); Result.getComplexFloatImag().changeSign(); } else if (!RHSReal) { Result.getComplexFloatImag().subtract(RHS.getComplexFloatImag(), APFloat::rmNearestTiesToEven); } } else { Result.getComplexIntReal() -= RHS.getComplexIntReal(); Result.getComplexIntImag() -= RHS.getComplexIntImag(); } break; case BO_Mul: if (Result.isComplexFloat()) { // This is an implementation of complex multiplication according to the // constraints laid out in C11 Annex G. The implemantion uses the // following naming scheme: // (a + ib) * (c + id) ComplexValue LHS = Result; APFloat &A = LHS.getComplexFloatReal(); APFloat &B = LHS.getComplexFloatImag(); APFloat &C = RHS.getComplexFloatReal(); APFloat &D = RHS.getComplexFloatImag(); APFloat &ResR = Result.getComplexFloatReal(); APFloat &ResI = Result.getComplexFloatImag(); if (LHSReal) { assert(!RHSReal && "Cannot have two real operands for a complex op!"); ResR = A * C; ResI = A * D; } else if (RHSReal) { ResR = C * A; ResI = C * B; } else { // In the fully general case, we need to handle NaNs and infinities // robustly. APFloat AC = A * C; APFloat BD = B * D; APFloat AD = A * D; APFloat BC = B * C; ResR = AC - BD; ResI = AD + BC; if (ResR.isNaN() && ResI.isNaN()) { bool Recalc = false; if (A.isInfinity() || B.isInfinity()) { A = APFloat::copySign( APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); B = APFloat::copySign( APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); if (C.isNaN()) C = APFloat::copySign(APFloat(C.getSemantics()), C); if (D.isNaN()) D = APFloat::copySign(APFloat(D.getSemantics()), D); Recalc = true; } if (C.isInfinity() || D.isInfinity()) { C = APFloat::copySign( APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); D = APFloat::copySign( APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); if (A.isNaN()) A = APFloat::copySign(APFloat(A.getSemantics()), A); if (B.isNaN()) B = APFloat::copySign(APFloat(B.getSemantics()), B); Recalc = true; } if (!Recalc && (AC.isInfinity() || BD.isInfinity() || AD.isInfinity() || BC.isInfinity())) { if (A.isNaN()) A = APFloat::copySign(APFloat(A.getSemantics()), A); if (B.isNaN()) B = APFloat::copySign(APFloat(B.getSemantics()), B); if (C.isNaN()) C = APFloat::copySign(APFloat(C.getSemantics()), C); if (D.isNaN()) D = APFloat::copySign(APFloat(D.getSemantics()), D); Recalc = true; } if (Recalc) { ResR = APFloat::getInf(A.getSemantics()) * (A * C - B * D); ResI = APFloat::getInf(A.getSemantics()) * (A * D + B * C); } } } } else { ComplexValue LHS = Result; Result.getComplexIntReal() = (LHS.getComplexIntReal() * RHS.getComplexIntReal() - LHS.getComplexIntImag() * RHS.getComplexIntImag()); Result.getComplexIntImag() = (LHS.getComplexIntReal() * RHS.getComplexIntImag() + LHS.getComplexIntImag() * RHS.getComplexIntReal()); } break; case BO_Div: if (Result.isComplexFloat()) { // This is an implementation of complex division according to the // constraints laid out in C11 Annex G. The implemantion uses the // following naming scheme: // (a + ib) / (c + id) ComplexValue LHS = Result; APFloat &A = LHS.getComplexFloatReal(); APFloat &B = LHS.getComplexFloatImag(); APFloat &C = RHS.getComplexFloatReal(); APFloat &D = RHS.getComplexFloatImag(); APFloat &ResR = Result.getComplexFloatReal(); APFloat &ResI = Result.getComplexFloatImag(); if (RHSReal) { ResR = A / C; ResI = B / C; } else { if (LHSReal) { // No real optimizations we can do here, stub out with zero. B = APFloat::getZero(A.getSemantics()); } int DenomLogB = 0; APFloat MaxCD = maxnum(abs(C), abs(D)); if (MaxCD.isFinite()) { DenomLogB = ilogb(MaxCD); C = scalbn(C, -DenomLogB, APFloat::rmNearestTiesToEven); D = scalbn(D, -DenomLogB, APFloat::rmNearestTiesToEven); } APFloat Denom = C * C + D * D; ResR = scalbn((A * C + B * D) / Denom, -DenomLogB, APFloat::rmNearestTiesToEven); ResI = scalbn((B * C - A * D) / Denom, -DenomLogB, APFloat::rmNearestTiesToEven); if (ResR.isNaN() && ResI.isNaN()) { if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) { ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A; ResI = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * B; } else if ((A.isInfinity() || B.isInfinity()) && C.isFinite() && D.isFinite()) { A = APFloat::copySign( APFloat(A.getSemantics(), A.isInfinity() ? 1 : 0), A); B = APFloat::copySign( APFloat(B.getSemantics(), B.isInfinity() ? 1 : 0), B); ResR = APFloat::getInf(ResR.getSemantics()) * (A * C + B * D); ResI = APFloat::getInf(ResI.getSemantics()) * (B * C - A * D); } else if (MaxCD.isInfinity() && A.isFinite() && B.isFinite()) { C = APFloat::copySign( APFloat(C.getSemantics(), C.isInfinity() ? 1 : 0), C); D = APFloat::copySign( APFloat(D.getSemantics(), D.isInfinity() ? 1 : 0), D); ResR = APFloat::getZero(ResR.getSemantics()) * (A * C + B * D); ResI = APFloat::getZero(ResI.getSemantics()) * (B * C - A * D); } } } } else { if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) return Error(E, diag::note_expr_divide_by_zero); ComplexValue LHS = Result; APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() + RHS.getComplexIntImag() * RHS.getComplexIntImag(); Result.getComplexIntReal() = (LHS.getComplexIntReal() * RHS.getComplexIntReal() + LHS.getComplexIntImag() * RHS.getComplexIntImag()) / Den; Result.getComplexIntImag() = (LHS.getComplexIntImag() * RHS.getComplexIntReal() - LHS.getComplexIntReal() * RHS.getComplexIntImag()) / Den; } break; } return true; } bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { // Get the operand value into 'Result'. if (!Visit(E->getSubExpr())) return false; switch (E->getOpcode()) { default: return Error(E); case UO_Extension: return true; case UO_Plus: // The result is always just the subexpr. return true; case UO_Minus: if (Result.isComplexFloat()) { Result.getComplexFloatReal().changeSign(); Result.getComplexFloatImag().changeSign(); } else { Result.getComplexIntReal() = -Result.getComplexIntReal(); Result.getComplexIntImag() = -Result.getComplexIntImag(); } return true; case UO_Not: if (Result.isComplexFloat()) Result.getComplexFloatImag().changeSign(); else Result.getComplexIntImag() = -Result.getComplexIntImag(); return true; } } bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) { if (E->getNumInits() == 2) { if (E->getType()->isComplexType()) { Result.makeComplexFloat(); if (!EvaluateFloat(E->getInit(0), Result.FloatReal, Info)) return false; if (!EvaluateFloat(E->getInit(1), Result.FloatImag, Info)) return false; } else { Result.makeComplexInt(); if (!EvaluateInteger(E->getInit(0), Result.IntReal, Info)) return false; if (!EvaluateInteger(E->getInit(1), Result.IntImag, Info)) return false; } return true; } return ExprEvaluatorBaseTy::VisitInitListExpr(E); } //===----------------------------------------------------------------------===// // Atomic expression evaluation, essentially just handling the NonAtomicToAtomic // implicit conversion. //===----------------------------------------------------------------------===// namespace { class AtomicExprEvaluator : public ExprEvaluatorBase { APValue &Result; public: AtomicExprEvaluator(EvalInfo &Info, APValue &Result) : ExprEvaluatorBaseTy(Info), Result(Result) {} bool Success(const APValue &V, const Expr *E) { Result = V; return true; } bool ZeroInitialization(const Expr *E) { ImplicitValueInitExpr VIE( E->getType()->castAs()->getValueType()); return Evaluate(Result, Info, &VIE); } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_NonAtomicToAtomic: return Evaluate(Result, Info, E->getSubExpr()); } } }; } // end anonymous namespace static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isAtomicType()); return AtomicExprEvaluator(Info, Result).Visit(E); } //===----------------------------------------------------------------------===// // Void expression evaluation, primarily for a cast to void on the LHS of a // comma operator //===----------------------------------------------------------------------===// namespace { class VoidExprEvaluator : public ExprEvaluatorBase { public: VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {} bool Success(const APValue &V, const Expr *e) { return true; } bool VisitCastExpr(const CastExpr *E) { switch (E->getCastKind()) { default: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_ToVoid: VisitIgnoredValue(E->getSubExpr()); return true; } } bool VisitCallExpr(const CallExpr *E) { switch (E->getBuiltinCallee()) { default: return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__assume: case Builtin::BI__builtin_assume: // The argument is not evaluated! return true; } } }; } // end anonymous namespace static bool EvaluateVoid(const Expr *E, EvalInfo &Info) { assert(E->isRValue() && E->getType()->isVoidType()); return VoidExprEvaluator(Info).Visit(E); } //===----------------------------------------------------------------------===// // Top level Expr::EvaluateAsRValue method. //===----------------------------------------------------------------------===// static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { // In C, function designators are not lvalues, but we evaluate them as if they // are. QualType T = E->getType(); if (E->isGLValue() || T->isFunctionType()) { LValue LV; if (!EvaluateLValue(E, LV, Info)) return false; LV.moveInto(Result); } else if (T->isVectorType()) { if (!EvaluateVector(E, Result, Info)) return false; } else if (T->isIntegralOrEnumerationType()) { if (!IntExprEvaluator(Info, Result).Visit(E)) return false; } else if (T->hasPointerRepresentation()) { LValue LV; if (!EvaluatePointer(E, LV, Info)) return false; LV.moveInto(Result); } else if (T->isRealFloatingType()) { llvm::APFloat F(0.0); if (!EvaluateFloat(E, F, Info)) return false; Result = APValue(F); } else if (T->isAnyComplexType()) { ComplexValue C; if (!EvaluateComplex(E, C, Info)) return false; C.moveInto(Result); } else if (T->isMemberPointerType()) { MemberPtr P; if (!EvaluateMemberPointer(E, P, Info)) return false; P.moveInto(Result); return true; } else if (T->isArrayType()) { LValue LV; LV.set(E, Info.CurrentCall->Index); APValue &Value = Info.CurrentCall->createTemporary(E, false); if (!EvaluateArray(E, LV, Value, Info)) return false; Result = Value; } else if (T->isRecordType()) { LValue LV; LV.set(E, Info.CurrentCall->Index); APValue &Value = Info.CurrentCall->createTemporary(E, false); if (!EvaluateRecord(E, LV, Value, Info)) return false; Result = Value; } else if (T->isVoidType()) { if (!Info.getLangOpts().CPlusPlus11) Info.CCEDiag(E, diag::note_constexpr_nonliteral) << E->getType(); if (!EvaluateVoid(E, Info)) return false; } else if (T->isAtomicType()) { if (!EvaluateAtomic(E, Result, Info)) return false; } else if (Info.getLangOpts().CPlusPlus11) { Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; } else { Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); return false; } return true; } /// EvaluateInPlace - Evaluate an expression in-place in an APValue. In some /// cases, the in-place evaluation is essential, since later initializers for /// an object can indirectly refer to subobjects which were initialized earlier. static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This, const Expr *E, bool AllowNonLiteralTypes) { assert(!E->isValueDependent()); if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This)) return false; if (E->isRValue()) { // Evaluate arrays and record types in-place, so that later initializers can // refer to earlier-initialized members of the object. if (E->getType()->isArrayType()) return EvaluateArray(E, This, Result, Info); else if (E->getType()->isRecordType()) return EvaluateRecord(E, This, Result, Info); } // For any other type, in-place evaluation is unimportant. return Evaluate(Result, Info, E); } /// EvaluateAsRValue - Try to evaluate this expression, performing an implicit /// lvalue-to-rvalue cast if it is an lvalue. static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) { if (E->getType().isNull()) return false; if (!CheckLiteralType(Info, E)) return false; if (!::Evaluate(Result, Info, E)) return false; if (E->isGLValue()) { LValue LV; LV.setFrom(Info.Ctx, Result); if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) return false; } // Check this core constant expression is a constant expression. return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result); } static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, const ASTContext &Ctx, bool &IsConst) { // Fast-path evaluations of integer literals, since we sometimes see files // containing vast quantities of these. if (const IntegerLiteral *L = dyn_cast(Exp)) { Result.Val = APValue(APSInt(L->getValue(), L->getType()->isUnsignedIntegerType())); IsConst = true; return true; } // This case should be rare, but we need to check it before we check on // the type below. if (Exp->getType().isNull()) { IsConst = false; return true; } // FIXME: Evaluating values of large array and record types can cause // performance problems. Only do so in C++11 for now. if (Exp->isRValue() && (Exp->getType()->isArrayType() || Exp->getType()->isRecordType()) && !Ctx.getLangOpts().CPlusPlus11) { IsConst = false; return true; } return false; } /// EvaluateAsRValue - Return true if this is a constant which we can fold using /// any crazy technique (that has nothing to do with language standards) that /// we want to. If this function returns true, it returns the folded constant /// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion /// will be applied to the result. bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { bool IsConst; if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) return IsConst; EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); return ::EvaluateAsRValue(Info, this, Result.Val); } bool Expr::EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const { EvalResult Scratch; return EvaluateAsRValue(Scratch, Ctx) && HandleConversionToBool(Scratch.Val, Result); } static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, Expr::SideEffectsKind SEK) { return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) || (SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior); } bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { if (!getType()->isIntegralOrEnumerationType()) return false; EvalResult ExprResult; if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() || hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) return false; Result = ExprResult.Val.getInt(); return true; } bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects) const { if (!getType()->isRealFloatingType()) return false; EvalResult ExprResult; if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isFloat() || hasUnacceptableSideEffect(ExprResult, AllowSideEffects)) return false; Result = ExprResult.Val.getFloat(); return true; } bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); LValue LV; if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects || !CheckLValueConstantExpression(Info, getExprLoc(), Ctx.getLValueReferenceType(getType()), LV)) return false; LV.moveInto(Result.Val); return true; } bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, const VarDecl *VD, SmallVectorImpl &Notes) const { // FIXME: Evaluating initializers for large array and record types can cause // performance problems. Only do so in C++11 for now. if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) && !Ctx.getLangOpts().CPlusPlus11) return false; Expr::EvalStatus EStatus; EStatus.Diag = &Notes; EvalInfo InitInfo(Ctx, EStatus, VD->isConstexpr() ? EvalInfo::EM_ConstantExpression : EvalInfo::EM_ConstantFold); InitInfo.setEvaluatingDecl(VD, Value); LValue LVal; LVal.set(VD); // C++11 [basic.start.init]p2: // Variables with static storage duration or thread storage duration shall be // zero-initialized before any other initialization takes place. // This behavior is not present in C. if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() && !VD->getType()->isReferenceType()) { ImplicitValueInitExpr VIE(VD->getType()); if (!EvaluateInPlace(Value, InitInfo, LVal, &VIE, /*AllowNonLiteralTypes=*/true)) return false; } if (!EvaluateInPlace(Value, InitInfo, LVal, this, /*AllowNonLiteralTypes=*/true) || EStatus.HasSideEffects) return false; return CheckConstantExpression(InitInfo, VD->getLocation(), VD->getType(), Value); } /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be /// constant folded, but discard the result. bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { EvalResult Result; return EvaluateAsRValue(Result, Ctx) && !hasUnacceptableSideEffect(Result, SEK); } APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl *Diag) const { EvalResult EvalResult; EvalResult.Diag = Diag; bool Result = EvaluateAsRValue(EvalResult, Ctx); (void)Result; assert(Result && "Could not evaluate expression"); assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); return EvalResult.Val.getInt(); } void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; EvalResult EvalResult; if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); (void)::EvaluateAsRValue(Info, this, EvalResult.Val); } } bool Expr::EvalResult::isGlobalLValue() const { assert(Val.isLValue()); return IsGlobalLValue(Val.getLValueBase()); } /// isIntegerConstantExpr - this recursive routine will test if an expression is /// an integer constant expression. /// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero, /// comma, etc // CheckICE - This function does the fundamental ICE checking: the returned // ICEDiag contains an ICEKind indicating whether the expression is an ICE, // and a (possibly null) SourceLocation indicating the location of the problem. // // Note that to reduce code duplication, this helper does no evaluation // itself; the caller checks whether the expression is evaluatable, and // in the rare cases where CheckICE actually cares about the evaluated // value, it calls into Evalute. namespace { enum ICEKind { /// This expression is an ICE. IK_ICE, /// This expression is not an ICE, but if it isn't evaluated, it's /// a legal subexpression for an ICE. This return value is used to handle /// the comma operator in C99 mode, and non-constant subexpressions. IK_ICEIfUnevaluated, /// This expression is not an ICE, and is not a legal subexpression for one. IK_NotICE }; struct ICEDiag { ICEKind Kind; SourceLocation Loc; ICEDiag(ICEKind IK, SourceLocation l) : Kind(IK), Loc(l) {} }; } static ICEDiag NoDiag() { return ICEDiag(IK_ICE, SourceLocation()); } static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || !EVResult.Val.isInt()) return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { assert(!E->isValueDependent() && "Should not see value dependent exprs!"); if (!E->getType()->isIntegralOrEnumerationType()) return ICEDiag(IK_NotICE, E->getLocStart()); switch (E->getStmtClass()) { #define ABSTRACT_STMT(Node) #define STMT(Node, Base) case Expr::Node##Class: #define EXPR(Node, Base) #include "clang/AST/StmtNodes.inc" case Expr::PredefinedExprClass: case Expr::FloatingLiteralClass: case Expr::ImaginaryLiteralClass: case Expr::StringLiteralClass: case Expr::ArraySubscriptExprClass: case Expr::OMPArraySectionExprClass: case Expr::MemberExprClass: case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: case Expr::DesignatedInitExprClass: case Expr::ArrayInitLoopExprClass: case Expr::ArrayInitIndexExprClass: case Expr::NoInitExprClass: case Expr::DesignatedInitUpdateExprClass: case Expr::ImplicitValueInitExprClass: case Expr::ParenListExprClass: case Expr::VAArgExprClass: case Expr::AddrLabelExprClass: case Expr::StmtExprClass: case Expr::CXXMemberCallExprClass: case Expr::CUDAKernelCallExprClass: case Expr::CXXDynamicCastExprClass: case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: case Expr::MSPropertyRefExprClass: case Expr::MSPropertySubscriptExprClass: case Expr::CXXNullPtrLiteralExprClass: case Expr::UserDefinedLiteralClass: case Expr::CXXThisExprClass: case Expr::CXXThrowExprClass: case Expr::CXXNewExprClass: case Expr::CXXDeleteExprClass: case Expr::CXXPseudoDestructorExprClass: case Expr::UnresolvedLookupExprClass: case Expr::TypoExprClass: case Expr::DependentScopeDeclRefExprClass: case Expr::CXXConstructExprClass: case Expr::CXXInheritedCtorInitExprClass: case Expr::CXXStdInitializerListExprClass: case Expr::CXXBindTemporaryExprClass: case Expr::ExprWithCleanupsClass: case Expr::CXXTemporaryObjectExprClass: case Expr::CXXUnresolvedConstructExprClass: case Expr::CXXDependentScopeMemberExprClass: case Expr::UnresolvedMemberExprClass: case Expr::ObjCStringLiteralClass: case Expr::ObjCBoxedExprClass: case Expr::ObjCArrayLiteralClass: case Expr::ObjCDictionaryLiteralClass: case Expr::ObjCEncodeExprClass: case Expr::ObjCMessageExprClass: case Expr::ObjCSelectorExprClass: case Expr::ObjCProtocolExprClass: case Expr::ObjCIvarRefExprClass: case Expr::ObjCPropertyRefExprClass: case Expr::ObjCSubscriptRefExprClass: case Expr::ObjCIsaExprClass: case Expr::ObjCAvailabilityCheckExprClass: case Expr::ShuffleVectorExprClass: case Expr::ConvertVectorExprClass: case Expr::BlockExprClass: case Expr::NoStmtClass: case Expr::OpaqueValueExprClass: case Expr::PackExpansionExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: case Expr::FunctionParmPackExprClass: case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::MaterializeTemporaryExprClass: case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: case Expr::LambdaExprClass: case Expr::CXXFoldExprClass: case Expr::CoawaitExprClass: case Expr::CoyieldExprClass: return ICEDiag(IK_NotICE, E->getLocStart()); case Expr::InitListExprClass: { // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the // form "T x = { a };" is equivalent to "T x = a;". // Unless we're initializing a reference, T is a scalar as it is known to be // of integral or enumeration type. if (E->isRValue()) if (cast(E)->getNumInits() == 1) return CheckICE(cast(E)->getInit(0), Ctx); return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: // GCC considers the GNU __null value to be an integral constant expression. return NoDiag(); case Expr::SubstNonTypeTemplateParmExprClass: return CheckICE(cast(E)->getReplacement(), Ctx); case Expr::ParenExprClass: return CheckICE(cast(E)->getSubExpr(), Ctx); case Expr::GenericSelectionExprClass: return CheckICE(cast(E)->getResultExpr(), Ctx); case Expr::IntegerLiteralClass: case Expr::CharacterLiteralClass: case Expr::ObjCBoolLiteralExprClass: case Expr::CXXBoolLiteralExprClass: case Expr::CXXScalarValueInitExprClass: case Expr::TypeTraitExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::CXXNoexceptExprClass: return NoDiag(); case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: { // C99 6.6/3 allows function calls within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an operand of (pointer to) function type. const CallExpr *CE = cast(E); if (CE->getBuiltinCallee()) return CheckEvalInICE(E, Ctx); return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::DeclRefExprClass: { if (isa(cast(E)->getDecl())) return NoDiag(); const ValueDecl *D = dyn_cast(cast(E)->getDecl()); if (Ctx.getLangOpts().CPlusPlus && D && IsConstNonVolatile(D->getType())) { // Parameter variables are never constants. Without this check, // getAnyInitializer() can find a default argument, which leads // to chaos. if (isa(D)) return ICEDiag(IK_NotICE, cast(E)->getLocation()); // C++ 7.1.5.1p2 // A variable of non-volatile const-qualified integral or enumeration // type initialized by an ICE can be used in ICEs. if (const VarDecl *Dcl = dyn_cast(D)) { if (!Dcl->getType()->isIntegralOrEnumerationType()) return ICEDiag(IK_NotICE, cast(E)->getLocation()); const VarDecl *VD; // Look for a declaration of this variable that has an initializer, and // check whether it is an ICE. if (Dcl->getAnyInitializer(VD) && VD->checkInitIsICE()) return NoDiag(); else return ICEDiag(IK_NotICE, cast(E)->getLocation()); } } return ICEDiag(IK_NotICE, E->getLocStart()); } case Expr::UnaryOperatorClass: { const UnaryOperator *Exp = cast(E); switch (Exp->getOpcode()) { case UO_PostInc: case UO_PostDec: case UO_PreInc: case UO_PreDec: case UO_AddrOf: case UO_Deref: case UO_Coawait: // C99 6.6/3 allows increment and decrement within unevaluated // subexpressions of constant expressions, but they can never be ICEs // because an ICE cannot contain an lvalue operand. return ICEDiag(IK_NotICE, E->getLocStart()); case UO_Extension: case UO_LNot: case UO_Plus: case UO_Minus: case UO_Not: case UO_Real: case UO_Imag: return CheckICE(Exp->getSubExpr(), Ctx); } // OffsetOf falls through here. } case Expr::OffsetOfExprClass: { // Note that per C99, offsetof must be an ICE. And AFAIK, using // EvaluateAsRValue matches the proposed gcc behavior for cases like // "offsetof(struct s{int x[4];}, x[1.0])". This doesn't affect // compliance: we should warn earlier for offsetof expressions with // array subscripts that aren't ICEs, and if the array subscripts // are ICEs, the value of the offsetof must be an integer constant. return CheckEvalInICE(E, Ctx); } case Expr::UnaryExprOrTypeTraitExprClass: { const UnaryExprOrTypeTraitExpr *Exp = cast(E); if ((Exp->getKind() == UETT_SizeOf) && Exp->getTypeOfArgument()->isVariableArrayType()) return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } case Expr::BinaryOperatorClass: { const BinaryOperator *Exp = cast(E); switch (Exp->getOpcode()) { case BO_PtrMemD: case BO_PtrMemI: case BO_Assign: case BO_MulAssign: case BO_DivAssign: case BO_RemAssign: case BO_AddAssign: case BO_SubAssign: case BO_ShlAssign: case BO_ShrAssign: case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: // C99 6.6/3 allows assignments within unevaluated subexpressions of // constant expressions, but they can never be ICEs because an ICE cannot // contain an lvalue operand. return ICEDiag(IK_NotICE, E->getLocStart()); case BO_Mul: case BO_Div: case BO_Rem: case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_LT: case BO_GT: case BO_LE: case BO_GE: case BO_EQ: case BO_NE: case BO_And: case BO_Xor: case BO_Or: case BO_Comma: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); if (Exp->getOpcode() == BO_Div || Exp->getOpcode() == BO_Rem) { // EvaluateAsRValue gives an error for undefined Div/Rem, so make sure // we don't evaluate one. if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) { llvm::APSInt REval = Exp->getRHS()->EvaluateKnownConstInt(Ctx); if (REval == 0) return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); if (REval.isSigned() && REval.isAllOnesValue()) { llvm::APSInt LEval = Exp->getLHS()->EvaluateKnownConstInt(Ctx); if (LEval.isMinSignedValue()) return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } } } if (Exp->getOpcode() == BO_Comma) { if (Ctx.getLangOpts().C99) { // C99 6.6p3 introduces a strange edge case: comma can be in an ICE // if it isn't evaluated. if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICE) return ICEDiag(IK_ICEIfUnevaluated, E->getLocStart()); } else { // In both C89 and C++, commas in ICEs are illegal. return ICEDiag(IK_NotICE, E->getLocStart()); } } return Worst(LHSResult, RHSResult); } case BO_LAnd: case BO_LOr: { ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx); ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx); if (LHSResult.Kind == IK_ICE && RHSResult.Kind == IK_ICEIfUnevaluated) { // Rare case where the RHS has a comma "side-effect"; we need // to actually check the condition to see whether the side // with the comma is evaluated. if ((Exp->getOpcode() == BO_LAnd) != (Exp->getLHS()->EvaluateKnownConstInt(Ctx) == 0)) return RHSResult; return NoDiag(); } return Worst(LHSResult, RHSResult); } } } case Expr::ImplicitCastExprClass: case Expr::CStyleCastExprClass: case Expr::CXXFunctionalCastExprClass: case Expr::CXXStaticCastExprClass: case Expr::CXXReinterpretCastExprClass: case Expr::CXXConstCastExprClass: case Expr::ObjCBridgedCastExprClass: { const Expr *SubExpr = cast(E)->getSubExpr(); if (isa(E)) { if (const FloatingLiteral *FL = dyn_cast(SubExpr->IgnoreParenImpCasts())) { unsigned DestWidth = Ctx.getIntWidth(E->getType()); bool DestSigned = E->getType()->isSignedIntegerOrEnumerationType(); APSInt IgnoredVal(DestWidth, !DestSigned); bool Ignored; // If the value does not fit in the destination type, the behavior is // undefined, so we are not required to treat it as a constant // expression. if (FL->getValue().convertToInteger(IgnoredVal, llvm::APFloat::rmTowardZero, &Ignored) & APFloat::opInvalidOp) return ICEDiag(IK_NotICE, E->getLocStart()); return NoDiag(); } } switch (cast(E)->getCastKind()) { case CK_LValueToRValue: case CK_AtomicToNonAtomic: case CK_NonAtomicToAtomic: case CK_NoOp: case CK_IntegralToBoolean: case CK_IntegralCast: return CheckICE(SubExpr, Ctx); default: return ICEDiag(IK_NotICE, E->getLocStart()); } } case Expr::BinaryConditionalOperatorClass: { const BinaryConditionalOperator *Exp = cast(E); ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx); if (CommonResult.Kind == IK_NotICE) return CommonResult; ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); if (FalseResult.Kind == IK_NotICE) return FalseResult; if (CommonResult.Kind == IK_ICEIfUnevaluated) return CommonResult; if (FalseResult.Kind == IK_ICEIfUnevaluated && Exp->getCommon()->EvaluateKnownConstInt(Ctx) != 0) return NoDiag(); return FalseResult; } case Expr::ConditionalOperatorClass: { const ConditionalOperator *Exp = cast(E); // If the condition (ignoring parens) is a __builtin_constant_p call, // then only the true side is actually considered in an integer constant // expression, and it is fully evaluated. This is an important GNU // extension. See GCC PR38377 for discussion. if (const CallExpr *CallCE = dyn_cast(Exp->getCond()->IgnoreParenCasts())) if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) return CheckEvalInICE(E, Ctx); ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx); if (CondResult.Kind == IK_NotICE) return CondResult; ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx); ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); if (TrueResult.Kind == IK_NotICE) return TrueResult; if (FalseResult.Kind == IK_NotICE) return FalseResult; if (CondResult.Kind == IK_ICEIfUnevaluated) return CondResult; if (TrueResult.Kind == IK_ICE && FalseResult.Kind == IK_ICE) return NoDiag(); // Rare case where the diagnostics depend on which side is evaluated // Note that if we get here, CondResult is 0, and at least one of // TrueResult and FalseResult is non-zero. if (Exp->getCond()->EvaluateKnownConstInt(Ctx) == 0) return FalseResult; return TrueResult; } case Expr::CXXDefaultArgExprClass: return CheckICE(cast(E)->getExpr(), Ctx); case Expr::CXXDefaultInitExprClass: return CheckICE(cast(E)->getExpr(), Ctx); case Expr::ChooseExprClass: { return CheckICE(cast(E)->getChosenSubExpr(), Ctx); } } llvm_unreachable("Invalid StmtClass!"); } /// Evaluate an expression as a C++11 integral constant expression. static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx, const Expr *E, llvm::APSInt *Value, SourceLocation *Loc) { if (!E->getType()->isIntegralOrEnumerationType()) { if (Loc) *Loc = E->getExprLoc(); return false; } APValue Result; if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc)) return false; if (!Result.isInt()) { if (Loc) *Loc = E->getExprLoc(); return false; } if (Value) *Value = Result.getInt(); return true; } bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc) const { if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc); ICEDiag D = CheckICE(this, Ctx); if (D.Kind != IK_ICE) { if (Loc) *Loc = D.Loc; return false; } return true; } bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, SourceLocation *Loc, bool isEvaluated) const { if (Ctx.getLangOpts().CPlusPlus11) return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); if (!isIntegerConstantExpr(Ctx, Loc)) return false; // The only possible side-effects here are due to UB discovered in the // evaluation (for instance, INT_MAX + 1). In such a case, we are still // required to treat the expression as an ICE, so we produce the folded // value. if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects)) llvm_unreachable("ICE cannot be evaluated!"); return true; } bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { return CheckICE(this, Ctx).Kind == IK_ICE; } bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result, SourceLocation *Loc) const { // We support this checking in C++98 mode in order to diagnose compatibility // issues. assert(Ctx.getLangOpts().CPlusPlus); // Build evaluation settings. Expr::EvalStatus Status; SmallVector Diags; Status.Diag = &Diags; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); APValue Scratch; bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch); if (!Diags.empty()) { IsConstExpr = false; if (Loc) *Loc = Diags[0].first; } else if (!IsConstExpr) { // FIXME: This shouldn't happen. if (Loc) *Loc = getExprLoc(); } return IsConstExpr; } bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, const FunctionDecl *Callee, ArrayRef Args, const Expr *This) const { Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); LValue ThisVal; const LValue *ThisPtr = nullptr; if (This) { #ifndef NDEBUG auto *MD = dyn_cast(Callee); assert(MD && "Don't provide `this` for non-methods."); assert(!MD->isStatic() && "Don't provide `this` for static methods."); #endif if (EvaluateObjectArgument(Info, This, ThisVal)) ThisPtr = &ThisVal; if (Info.EvalStatus.HasSideEffects) return false; } ArgVector ArgValues(Args.size()); for (ArrayRef::iterator I = Args.begin(), E = Args.end(); I != E; ++I) { if ((*I)->isValueDependent() || !Evaluate(ArgValues[I - Args.begin()], Info, *I)) // If evaluation fails, throw away the argument entirely. ArgValues[I - Args.begin()] = APValue(); if (Info.EvalStatus.HasSideEffects) return false; } // Build fake call to Callee. CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr, ArgValues.data()); return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects; } bool Expr::isPotentialConstantExpr(const FunctionDecl *FD, SmallVectorImpl< PartialDiagnosticAt> &Diags) { // FIXME: It would be useful to check constexpr function templates, but at the // moment the constant expression evaluator cannot cope with the non-rigorous // ASTs which we build for dependent expressions. if (FD->isDependentContext()) return true; Expr::EvalStatus Status; Status.Diag = &Diags; EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpression); const CXXMethodDecl *MD = dyn_cast(FD); const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; // Fabricate an arbitrary expression on the stack and pretend that it // is a temporary being used as the 'this' pointer. LValue This; ImplicitValueInitExpr VIE(RD ? Info.Ctx.getRecordType(RD) : Info.Ctx.IntTy); This.set(&VIE, Info.CurrentCall->Index); ArrayRef Args; APValue Scratch; if (const CXXConstructorDecl *CD = dyn_cast(FD)) { // Evaluate the call as a constant initializer, to allow the construction // of objects of non-literal types. Info.setEvaluatingDecl(This.getLValueBase(), Scratch); HandleConstructorCall(&VIE, This, Args, CD, Info, Scratch); } else { SourceLocation Loc = FD->getLocation(); HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr, Args, FD->getBody(), Info, Scratch, nullptr); } return Diags.empty(); } bool Expr::isPotentialConstantExprUnevaluated(Expr *E, const FunctionDecl *FD, SmallVectorImpl< PartialDiagnosticAt> &Diags) { Expr::EvalStatus Status; Status.Diag = &Diags; EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpressionUnevaluated); // Fabricate a call stack frame to give the arguments a plausible cover story. ArrayRef Args; ArgVector ArgValues(0); bool Success = EvaluateArgs(Args, ArgValues, Info); (void)Success; assert(Success && "Failed to set up arguments for potential constant evaluation"); CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data()); APValue ResultScratch; Evaluate(ResultScratch, Info, E); return Diags.empty(); } bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, unsigned Type) const { if (!getType()->isPointerType()) return false; Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold); return tryEvaluateBuiltinObjectSize(this, Type, Info, Result); } Index: vendor/clang/dist/lib/CodeGen/CodeGenModule.h =================================================================== --- vendor/clang/dist/lib/CodeGen/CodeGenModule.h (revision 313882) +++ vendor/clang/dist/lib/CodeGen/CodeGenModule.h (revision 313883) @@ -1,1311 +1,1311 @@ //===--- CodeGenModule.h - Per-Module state for LLVM CodeGen ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This is the internal per-translation-unit state used for llvm translation. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H #define LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H #include "CGVTables.h" #include "CodeGenTypeCache.h" #include "CodeGenTypes.h" #include "SanitizerMetadata.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" #include "clang/AST/GlobalDecl.h" #include "clang/AST/Mangle.h" #include "clang/Basic/ABI.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/SanitizerBlacklist.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Transforms/Utils/SanitizerStats.h" namespace llvm { class Module; class Constant; class ConstantInt; class Function; class GlobalValue; class DataLayout; class FunctionType; class LLVMContext; class IndexedInstrProfReader; } namespace clang { class ASTContext; class AtomicType; class FunctionDecl; class IdentifierInfo; class ObjCMethodDecl; class ObjCImplementationDecl; class ObjCCategoryImplDecl; class ObjCProtocolDecl; class ObjCEncodeExpr; class BlockExpr; class CharUnits; class Decl; class Expr; class Stmt; class InitListExpr; class StringLiteral; class NamedDecl; class ValueDecl; class VarDecl; class LangOptions; class CodeGenOptions; class HeaderSearchOptions; class PreprocessorOptions; class DiagnosticsEngine; class AnnotateAttr; class CXXDestructorDecl; class Module; class CoverageSourceInfo; namespace CodeGen { class CallArgList; class CodeGenFunction; class CodeGenTBAA; class CGCXXABI; class CGDebugInfo; class CGObjCRuntime; class CGOpenCLRuntime; class CGOpenMPRuntime; class CGCUDARuntime; class BlockFieldFlags; class FunctionArgList; class CoverageMappingModuleGen; class TargetCodeGenInfo; enum ForDefinition_t : bool { NotForDefinition = false, ForDefinition = true }; struct OrderGlobalInits { unsigned int priority; unsigned int lex_order; OrderGlobalInits(unsigned int p, unsigned int l) : priority(p), lex_order(l) {} bool operator==(const OrderGlobalInits &RHS) const { return priority == RHS.priority && lex_order == RHS.lex_order; } bool operator<(const OrderGlobalInits &RHS) const { return std::tie(priority, lex_order) < std::tie(RHS.priority, RHS.lex_order); } }; struct ObjCEntrypoints { ObjCEntrypoints() { memset(this, 0, sizeof(*this)); } /// void objc_autoreleasePoolPop(void*); llvm::Constant *objc_autoreleasePoolPop; /// void *objc_autoreleasePoolPush(void); llvm::Constant *objc_autoreleasePoolPush; /// id objc_autorelease(id); llvm::Constant *objc_autorelease; /// id objc_autoreleaseReturnValue(id); llvm::Constant *objc_autoreleaseReturnValue; /// void objc_copyWeak(id *dest, id *src); llvm::Constant *objc_copyWeak; /// void objc_destroyWeak(id*); llvm::Constant *objc_destroyWeak; /// id objc_initWeak(id*, id); llvm::Constant *objc_initWeak; /// id objc_loadWeak(id*); llvm::Constant *objc_loadWeak; /// id objc_loadWeakRetained(id*); llvm::Constant *objc_loadWeakRetained; /// void objc_moveWeak(id *dest, id *src); llvm::Constant *objc_moveWeak; /// id objc_retain(id); llvm::Constant *objc_retain; /// id objc_retainAutorelease(id); llvm::Constant *objc_retainAutorelease; /// id objc_retainAutoreleaseReturnValue(id); llvm::Constant *objc_retainAutoreleaseReturnValue; /// id objc_retainAutoreleasedReturnValue(id); llvm::Constant *objc_retainAutoreleasedReturnValue; /// id objc_retainBlock(id); llvm::Constant *objc_retainBlock; /// void objc_release(id); llvm::Constant *objc_release; - /// id objc_storeStrong(id*, id); + /// void objc_storeStrong(id*, id); llvm::Constant *objc_storeStrong; /// id objc_storeWeak(id*, id); llvm::Constant *objc_storeWeak; /// id objc_unsafeClaimAutoreleasedReturnValue(id); llvm::Constant *objc_unsafeClaimAutoreleasedReturnValue; /// A void(void) inline asm to use to mark that the return value of /// a call will be immediately retain. llvm::InlineAsm *retainAutoreleasedReturnValueMarker; /// void clang.arc.use(...); llvm::Constant *clang_arc_use; }; /// This class records statistics on instrumentation based profiling. class InstrProfStats { uint32_t VisitedInMainFile; uint32_t MissingInMainFile; uint32_t Visited; uint32_t Missing; uint32_t Mismatched; public: InstrProfStats() : VisitedInMainFile(0), MissingInMainFile(0), Visited(0), Missing(0), Mismatched(0) {} /// Record that we've visited a function and whether or not that function was /// in the main source file. void addVisited(bool MainFile) { if (MainFile) ++VisitedInMainFile; ++Visited; } /// Record that a function we've visited has no profile data. void addMissing(bool MainFile) { if (MainFile) ++MissingInMainFile; ++Missing; } /// Record that a function we've visited has mismatched profile data. void addMismatched(bool MainFile) { ++Mismatched; } /// Whether or not the stats we've gathered indicate any potential problems. bool hasDiagnostics() { return Missing || Mismatched; } /// Report potential problems we've found to \c Diags. void reportDiagnostics(DiagnosticsEngine &Diags, StringRef MainFile); }; /// A pair of helper functions for a __block variable. class BlockByrefHelpers : public llvm::FoldingSetNode { // MSVC requires this type to be complete in order to process this // header. public: llvm::Constant *CopyHelper; llvm::Constant *DisposeHelper; /// The alignment of the field. This is important because /// different offsets to the field within the byref struct need to /// have different helper functions. CharUnits Alignment; BlockByrefHelpers(CharUnits alignment) : Alignment(alignment) {} BlockByrefHelpers(const BlockByrefHelpers &) = default; virtual ~BlockByrefHelpers(); void Profile(llvm::FoldingSetNodeID &id) const { id.AddInteger(Alignment.getQuantity()); profileImpl(id); } virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0; virtual bool needsCopy() const { return true; } virtual void emitCopy(CodeGenFunction &CGF, Address dest, Address src) = 0; virtual bool needsDispose() const { return true; } virtual void emitDispose(CodeGenFunction &CGF, Address field) = 0; }; /// This class organizes the cross-function state that is used while generating /// LLVM code. class CodeGenModule : public CodeGenTypeCache { CodeGenModule(const CodeGenModule &) = delete; void operator=(const CodeGenModule &) = delete; public: struct Structor { Structor() : Priority(0), Initializer(nullptr), AssociatedData(nullptr) {} Structor(int Priority, llvm::Constant *Initializer, llvm::Constant *AssociatedData) : Priority(Priority), Initializer(Initializer), AssociatedData(AssociatedData) {} int Priority; llvm::Constant *Initializer; llvm::Constant *AssociatedData; }; typedef std::vector CtorList; private: ASTContext &Context; const LangOptions &LangOpts; const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const CodeGenOptions &CodeGenOpts; llvm::Module &TheModule; DiagnosticsEngine &Diags; const TargetInfo &Target; std::unique_ptr ABI; llvm::LLVMContext &VMContext; std::unique_ptr TBAA; mutable std::unique_ptr TheTargetCodeGenInfo; // This should not be moved earlier, since its initialization depends on some // of the previous reference members being already initialized and also checks // if TheTargetCodeGenInfo is NULL CodeGenTypes Types; /// Holds information about C++ vtables. CodeGenVTables VTables; std::unique_ptr ObjCRuntime; std::unique_ptr OpenCLRuntime; std::unique_ptr OpenMPRuntime; std::unique_ptr CUDARuntime; std::unique_ptr DebugInfo; std::unique_ptr ObjCData; llvm::MDNode *NoObjCARCExceptionsMetadata = nullptr; std::unique_ptr PGOReader; InstrProfStats PGOStats; std::unique_ptr SanStats; // A set of references that have only been seen via a weakref so far. This is // used to remove the weak of the reference if we ever see a direct reference // or a definition. llvm::SmallPtrSet WeakRefReferences; /// This contains all the decls which have definitions but/ which are deferred /// for emission and therefore should only be output if they are actually /// used. If a decl is in this, then it is known to have not been referenced /// yet. std::map DeferredDecls; /// This is a list of deferred decls which we have seen that *are* actually /// referenced. These get code generated when the module is done. struct DeferredGlobal { DeferredGlobal(llvm::GlobalValue *GV, GlobalDecl GD) : GV(GV), GD(GD) {} llvm::TrackingVH GV; GlobalDecl GD; }; std::vector DeferredDeclsToEmit; void addDeferredDeclToEmit(llvm::GlobalValue *GV, GlobalDecl GD) { DeferredDeclsToEmit.emplace_back(GV, GD); } /// List of alias we have emitted. Used to make sure that what they point to /// is defined once we get to the end of the of the translation unit. std::vector Aliases; typedef llvm::StringMap > ReplacementsTy; ReplacementsTy Replacements; /// List of global values to be replaced with something else. Used when we /// want to replace a GlobalValue but can't identify it by its mangled name /// anymore (because the name is already taken). llvm::SmallVector, 8> GlobalValReplacements; /// Set of global decls for which we already diagnosed mangled name conflict. /// Required to not issue a warning (on a mangling conflict) multiple times /// for the same decl. llvm::DenseSet DiagnosedConflictingDefinitions; /// A queue of (optional) vtables to consider emitting. std::vector DeferredVTables; /// List of global values which are required to be present in the object file; /// bitcast to i8*. This is used for forcing visibility of symbols which may /// otherwise be optimized out. std::vector LLVMUsed; std::vector LLVMCompilerUsed; /// Store the list of global constructors and their respective priorities to /// be emitted when the translation unit is complete. CtorList GlobalCtors; /// Store the list of global destructors and their respective priorities to be /// emitted when the translation unit is complete. CtorList GlobalDtors; /// An ordered map of canonical GlobalDecls to their mangled names. llvm::MapVector MangledDeclNames; llvm::StringMap Manglings; /// Global annotations. std::vector Annotations; /// Map used to get unique annotation strings. llvm::StringMap AnnotationStrings; llvm::StringMap CFConstantStringMap; llvm::DenseMap ConstantStringMap; llvm::DenseMap StaticLocalDeclMap; llvm::DenseMap StaticLocalDeclGuardMap; llvm::DenseMap MaterializedGlobalTemporaryMap; llvm::DenseMap AtomicSetterHelperFnMap; llvm::DenseMap AtomicGetterHelperFnMap; /// Map used to get unique type descriptor constants for sanitizers. llvm::DenseMap TypeDescriptorMap; /// Map used to track internal linkage functions declared within /// extern "C" regions. typedef llvm::MapVector StaticExternCMap; StaticExternCMap StaticExternCValues; /// \brief thread_local variables defined or used in this TU. std::vector CXXThreadLocals; /// \brief thread_local variables with initializers that need to run /// before any thread_local variable in this TU is odr-used. std::vector CXXThreadLocalInits; std::vector CXXThreadLocalInitVars; /// Global variables with initializers that need to run before main. std::vector CXXGlobalInits; /// When a C++ decl with an initializer is deferred, null is /// appended to CXXGlobalInits, and the index of that null is placed /// here so that the initializer will be performed in the correct /// order. Once the decl is emitted, the index is replaced with ~0U to ensure /// that we don't re-emit the initializer. llvm::DenseMap DelayedCXXInitPosition; typedef std::pair GlobalInitData; struct GlobalInitPriorityCmp { bool operator()(const GlobalInitData &LHS, const GlobalInitData &RHS) const { return LHS.first.priority < RHS.first.priority; } }; /// Global variables with initializers whose order of initialization is set by /// init_priority attribute. SmallVector PrioritizedCXXGlobalInits; /// Global destructor functions and arguments that need to run on termination. std::vector > CXXGlobalDtors; /// \brief The complete set of modules that has been imported. llvm::SetVector ImportedModules; /// \brief The set of modules for which the module initializers /// have been emitted. llvm::SmallPtrSet EmittedModuleInitializers; /// \brief A vector of metadata strings. SmallVector LinkerOptionsMetadata; /// @name Cache for Objective-C runtime types /// @{ /// Cached reference to the class for constant strings. This value has type /// int * but is actually an Obj-C class pointer. llvm::WeakVH CFConstantStringClassRef; /// \brief The type used to describe the state of a fast enumeration in /// Objective-C's for..in loop. QualType ObjCFastEnumerationStateType; /// @} /// Lazily create the Objective-C runtime void createObjCRuntime(); void createOpenCLRuntime(); void createOpenMPRuntime(); void createCUDARuntime(); bool isTriviallyRecursive(const FunctionDecl *F); bool shouldEmitFunction(GlobalDecl GD); /// Map used to be sure we don't emit the same CompoundLiteral twice. llvm::DenseMap EmittedCompoundLiterals; /// Map of the global blocks we've emitted, so that we don't have to re-emit /// them if the constexpr evaluator gets aggressive. llvm::DenseMap EmittedGlobalBlocks; /// @name Cache for Blocks Runtime Globals /// @{ llvm::Constant *NSConcreteGlobalBlock = nullptr; llvm::Constant *NSConcreteStackBlock = nullptr; llvm::Constant *BlockObjectAssign = nullptr; llvm::Constant *BlockObjectDispose = nullptr; llvm::Type *BlockDescriptorType = nullptr; llvm::Type *GenericBlockLiteralType = nullptr; struct { int GlobalUniqueCount; } Block; /// void @llvm.lifetime.start(i64 %size, i8* nocapture ) llvm::Constant *LifetimeStartFn = nullptr; /// void @llvm.lifetime.end(i64 %size, i8* nocapture ) llvm::Constant *LifetimeEndFn = nullptr; GlobalDecl initializedGlobalDecl; std::unique_ptr SanitizerMD; /// @} llvm::DenseMap DeferredEmptyCoverageMappingDecls; std::unique_ptr CoverageMapping; /// Mapping from canonical types to their metadata identifiers. We need to /// maintain this mapping because identifiers may be formed from distinct /// MDNodes. llvm::DenseMap MetadataIdMap; public: CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts, const PreprocessorOptions &ppopts, const CodeGenOptions &CodeGenOpts, llvm::Module &M, DiagnosticsEngine &Diags, CoverageSourceInfo *CoverageInfo = nullptr); ~CodeGenModule(); void clear(); /// Finalize LLVM code generation. void Release(); /// Return a reference to the configured Objective-C runtime. CGObjCRuntime &getObjCRuntime() { if (!ObjCRuntime) createObjCRuntime(); return *ObjCRuntime; } /// Return true iff an Objective-C runtime has been configured. bool hasObjCRuntime() { return !!ObjCRuntime; } /// Return a reference to the configured OpenCL runtime. CGOpenCLRuntime &getOpenCLRuntime() { assert(OpenCLRuntime != nullptr); return *OpenCLRuntime; } /// Return a reference to the configured OpenMP runtime. CGOpenMPRuntime &getOpenMPRuntime() { assert(OpenMPRuntime != nullptr); return *OpenMPRuntime; } /// Return a reference to the configured CUDA runtime. CGCUDARuntime &getCUDARuntime() { assert(CUDARuntime != nullptr); return *CUDARuntime; } ObjCEntrypoints &getObjCEntrypoints() const { assert(ObjCData != nullptr); return *ObjCData; } InstrProfStats &getPGOStats() { return PGOStats; } llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); } CoverageMappingModuleGen *getCoverageMapping() const { return CoverageMapping.get(); } llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) { return StaticLocalDeclMap[D]; } void setStaticLocalDeclAddress(const VarDecl *D, llvm::Constant *C) { StaticLocalDeclMap[D] = C; } llvm::Constant * getOrCreateStaticVarDecl(const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage); llvm::GlobalVariable *getStaticLocalDeclGuardAddress(const VarDecl *D) { return StaticLocalDeclGuardMap[D]; } void setStaticLocalDeclGuardAddress(const VarDecl *D, llvm::GlobalVariable *C) { StaticLocalDeclGuardMap[D] = C; } bool lookupRepresentativeDecl(StringRef MangledName, GlobalDecl &Result) const; llvm::Constant *getAtomicSetterHelperFnMap(QualType Ty) { return AtomicSetterHelperFnMap[Ty]; } void setAtomicSetterHelperFnMap(QualType Ty, llvm::Constant *Fn) { AtomicSetterHelperFnMap[Ty] = Fn; } llvm::Constant *getAtomicGetterHelperFnMap(QualType Ty) { return AtomicGetterHelperFnMap[Ty]; } void setAtomicGetterHelperFnMap(QualType Ty, llvm::Constant *Fn) { AtomicGetterHelperFnMap[Ty] = Fn; } llvm::Constant *getTypeDescriptorFromMap(QualType Ty) { return TypeDescriptorMap[Ty]; } void setTypeDescriptorInMap(QualType Ty, llvm::Constant *C) { TypeDescriptorMap[Ty] = C; } CGDebugInfo *getModuleDebugInfo() { return DebugInfo.get(); } llvm::MDNode *getNoObjCARCExceptionsMetadata() { if (!NoObjCARCExceptionsMetadata) NoObjCARCExceptionsMetadata = llvm::MDNode::get(getLLVMContext(), None); return NoObjCARCExceptionsMetadata; } ASTContext &getContext() const { return Context; } const LangOptions &getLangOpts() const { return LangOpts; } const HeaderSearchOptions &getHeaderSearchOpts() const { return HeaderSearchOpts; } const PreprocessorOptions &getPreprocessorOpts() const { return PreprocessorOpts; } const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } llvm::Module &getModule() const { return TheModule; } DiagnosticsEngine &getDiags() const { return Diags; } const llvm::DataLayout &getDataLayout() const { return TheModule.getDataLayout(); } const TargetInfo &getTarget() const { return Target; } const llvm::Triple &getTriple() const { return Target.getTriple(); } bool supportsCOMDAT() const; void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO); CGCXXABI &getCXXABI() const { return *ABI; } llvm::LLVMContext &getLLVMContext() { return VMContext; } bool shouldUseTBAA() const { return TBAA != nullptr; } const TargetCodeGenInfo &getTargetCodeGenInfo(); CodeGenTypes &getTypes() { return Types; } CodeGenVTables &getVTables() { return VTables; } ItaniumVTableContext &getItaniumVTableContext() { return VTables.getItaniumVTableContext(); } MicrosoftVTableContext &getMicrosoftVTableContext() { return VTables.getMicrosoftVTableContext(); } CtorList &getGlobalCtors() { return GlobalCtors; } CtorList &getGlobalDtors() { return GlobalDtors; } llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); /// Return the path-aware tag for given base type, access node and offset. llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN, uint64_t O); bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); bool isPaddedAtomicType(QualType type); bool isPaddedAtomicType(const AtomicType *type); /// Decorate the instruction with a TBAA tag. For scalar TBAA, the tag /// is the same as the type. For struct-path aware TBAA, the tag /// is different from the type: base type, access type and offset. /// When ConvertTypeToTag is true, we create a tag based on the scalar type. void DecorateInstructionWithTBAA(llvm::Instruction *Inst, llvm::MDNode *TBAAInfo, bool ConvertTypeToTag = true); /// Adds !invariant.barrier !tag to instruction void DecorateInstructionWithInvariantGroup(llvm::Instruction *I, const CXXRecordDecl *RD); /// Emit the given number of characters as a value of type size_t. llvm::ConstantInt *getSize(CharUnits numChars); /// Set the visibility for the given LLVM GlobalValue. void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const; /// Set the TLS mode for the given LLVM GlobalValue for the thread-local /// variable declaration D. void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const; static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V) { switch (V) { case DefaultVisibility: return llvm::GlobalValue::DefaultVisibility; case HiddenVisibility: return llvm::GlobalValue::HiddenVisibility; case ProtectedVisibility: return llvm::GlobalValue::ProtectedVisibility; } llvm_unreachable("unknown visibility!"); } llvm::Constant *GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition = NotForDefinition); /// Will return a global variable of the given type. If a variable with a /// different type already exists then a new variable with the right type /// will be created and all uses of the old variable will be replaced with a /// bitcast to the new variable. llvm::GlobalVariable * CreateOrReplaceCXXRuntimeVariable(StringRef Name, llvm::Type *Ty, llvm::GlobalValue::LinkageTypes Linkage); llvm::Function * CreateGlobalInitOrDestructFunction(llvm::FunctionType *ty, const Twine &name, const CGFunctionInfo &FI, SourceLocation Loc = SourceLocation(), bool TLS = false); /// Return the address space of the underlying global variable for D, as /// determined by its declaration. Normally this is the same as the address /// space of D's type, but in CUDA, address spaces are associated with /// declarations, not types. unsigned GetGlobalVarAddressSpace(const VarDecl *D, unsigned AddrSpace); /// Return the llvm::Constant for the address of the given global variable. /// If Ty is non-null and if the global doesn't exist, then it will be created /// with the specified type instead of whatever the normal requested type /// would be. If IsForDefinition is true, it is guranteed that an actual /// global with type Ty will be returned, not conversion of a variable with /// the same mangled name but some other type. llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D, llvm::Type *Ty = nullptr, ForDefinition_t IsForDefinition = NotForDefinition); /// Return the address of the given function. If Ty is non-null, then this /// function will use the specified type if it has to create it. llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr, bool ForVTable = false, bool DontDefer = false, ForDefinition_t IsForDefinition = NotForDefinition); /// Get the address of the RTTI descriptor for the given type. llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false); /// Get the address of a uuid descriptor . ConstantAddress GetAddrOfUuidDescriptor(const CXXUuidofExpr* E); /// Get the address of the thunk for the given global decl. llvm::Constant *GetAddrOfThunk(GlobalDecl GD, const ThunkInfo &Thunk); /// Get a reference to the target of VD. ConstantAddress GetWeakRefReference(const ValueDecl *VD); /// Returns the assumed alignment of an opaque pointer to the given class. CharUnits getClassPointerAlignment(const CXXRecordDecl *CD); /// Returns the assumed alignment of a virtual base of a class. CharUnits getVBaseAlignment(CharUnits DerivedAlign, const CXXRecordDecl *Derived, const CXXRecordDecl *VBase); /// Given a class pointer with an actual known alignment, and the /// expected alignment of an object at a dynamic offset w.r.t that /// pointer, return the alignment to assume at the offset. CharUnits getDynamicOffsetAlignment(CharUnits ActualAlign, const CXXRecordDecl *Class, CharUnits ExpectedTargetAlign); CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, CastExpr::path_const_iterator End); /// Returns the offset from a derived class to a class. Returns null if the /// offset is 0. llvm::Constant * GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd); llvm::FoldingSet ByrefHelpersCache; /// Fetches the global unique block count. int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; } /// Fetches the type of a generic block descriptor. llvm::Type *getBlockDescriptorType(); /// The type of a generic block literal. llvm::Type *getGenericBlockLiteralType(); /// Gets the address of a block which requires no captures. llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, StringRef Name); /// Returns the address of a block which requires no caputres, or null if /// we've yet to emit the block for BE. llvm::Constant *getAddrOfGlobalBlockIfEmitted(const BlockExpr *BE) { return EmittedGlobalBlocks.lookup(BE); } /// Notes that BE's global block is available via Addr. Asserts that BE /// isn't already emitted. void setAddrOfGlobalBlock(const BlockExpr *BE, llvm::Constant *Addr); /// Return a pointer to a constant CFString object for the given string. ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal); /// Return a pointer to a constant NSString object for the given string. Or a /// user defined String object as defined via /// -fconstant-string-class=class_name option. ConstantAddress GetAddrOfConstantString(const StringLiteral *Literal); /// Return a constant array for the given string. llvm::Constant *GetConstantArrayFromStringLiteral(const StringLiteral *E); /// Return a pointer to a constant array for the given string literal. ConstantAddress GetAddrOfConstantStringFromLiteral(const StringLiteral *S, StringRef Name = ".str"); /// Return a pointer to a constant array for the given ObjCEncodeExpr node. ConstantAddress GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *); /// Returns a pointer to a character array containing the literal and a /// terminating '\0' character. The result has pointer to array type. /// /// \param GlobalName If provided, the name to use for the global (if one is /// created). ConstantAddress GetAddrOfConstantCString(const std::string &Str, const char *GlobalName = nullptr); /// Returns a pointer to a constant global variable for the given file-scope /// compound literal expression. ConstantAddress GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E); /// If it's been emitted already, returns the GlobalVariable corresponding to /// a compound literal. Otherwise, returns null. llvm::GlobalVariable * getAddrOfConstantCompoundLiteralIfEmitted(const CompoundLiteralExpr *E); /// Notes that CLE's GlobalVariable is GV. Asserts that CLE isn't already /// emitted. void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *CLE, llvm::GlobalVariable *GV); /// \brief Returns a pointer to a global variable representing a temporary /// with static or thread storage duration. ConstantAddress GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E, const Expr *Inner); /// \brief Retrieve the record type that describes the state of an /// Objective-C fast enumeration loop (for..in). QualType getObjCFastEnumerationStateType(); // Produce code for this constructor/destructor. This method doesn't try // to apply any ABI rules about which other constructors/destructors // are needed or if they are alias to each other. llvm::Function *codegenCXXStructor(const CXXMethodDecl *MD, StructorType Type); /// Return the address of the constructor/destructor of the given type. llvm::Constant * getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo = nullptr, llvm::FunctionType *FnType = nullptr, bool DontDefer = false, ForDefinition_t IsForDefinition = NotForDefinition); /// Given a builtin id for a function like "__builtin_fabsf", return a /// Function* for "fabsf". llvm::Constant *getBuiltinLibFunction(const FunctionDecl *FD, unsigned BuiltinID); llvm::Function *getIntrinsic(unsigned IID, ArrayRef Tys = None); /// Emit code for a single top level declaration. void EmitTopLevelDecl(Decl *D); /// \brief Stored a deferred empty coverage mapping for an unused /// and thus uninstrumented top level declaration. void AddDeferredUnusedCoverageMapping(Decl *D); /// \brief Remove the deferred empty coverage mapping as this /// declaration is actually instrumented. void ClearUnusedCoverageMapping(const Decl *D); /// \brief Emit all the deferred coverage mappings /// for the uninstrumented functions. void EmitDeferredUnusedCoverageMappings(); /// Tell the consumer that this variable has been instantiated. void HandleCXXStaticMemberVarInstantiation(VarDecl *VD); /// \brief If the declaration has internal linkage but is inside an /// extern "C" linkage specification, prepare to emit an alias for it /// to the expected name. template void MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV); /// Add a global to a list to be added to the llvm.used metadata. void addUsedGlobal(llvm::GlobalValue *GV); /// Add a global to a list to be added to the llvm.compiler.used metadata. void addCompilerUsedGlobal(llvm::GlobalValue *GV); /// Add a destructor and object to add to the C++ global destructor function. void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) { CXXGlobalDtors.emplace_back(DtorFn, Object); } /// Create a new runtime function with the specified type and name. llvm::Constant * CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(), bool Local = false); /// Create a new compiler builtin function with the specified type and name. llvm::Constant *CreateBuiltinFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeSet ExtraAttrs = llvm::AttributeSet()); /// Create a new runtime global variable with the specified type and name. llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty, StringRef Name); ///@name Custom Blocks Runtime Interfaces ///@{ llvm::Constant *getNSConcreteGlobalBlock(); llvm::Constant *getNSConcreteStackBlock(); llvm::Constant *getBlockObjectAssign(); llvm::Constant *getBlockObjectDispose(); ///@} llvm::Constant *getLLVMLifetimeStartFn(); llvm::Constant *getLLVMLifetimeEndFn(); // Make sure that this type is translated. void UpdateCompletedType(const TagDecl *TD); llvm::Constant *getMemberPointerConstant(const UnaryOperator *e); /// Try to emit the initializer for the given declaration as a constant; /// returns 0 if the expression cannot be emitted as a constant. llvm::Constant *EmitConstantInit(const VarDecl &D, CodeGenFunction *CGF = nullptr); /// Try to emit the given expression as a constant; returns 0 if the /// expression cannot be emitted as a constant. llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType, CodeGenFunction *CGF = nullptr); /// Emit the given constant value as a constant, in the type's scalar /// representation. llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType, CodeGenFunction *CGF = nullptr); /// Emit the given constant value as a constant, in the type's memory /// representation. llvm::Constant *EmitConstantValueForMemory(const APValue &Value, QualType DestType, CodeGenFunction *CGF = nullptr); /// \brief Emit type info if type of an expression is a variably modified /// type. Also emit proper debug info for cast types. void EmitExplicitCastExprType(const ExplicitCastExpr *E, CodeGenFunction *CGF = nullptr); /// Return the result of value-initializing the given type, i.e. a null /// expression of the given type. This is usually, but not always, an LLVM /// null constant. llvm::Constant *EmitNullConstant(QualType T); /// Return a null constant appropriate for zero-initializing a base class with /// the given type. This is usually, but not always, an LLVM null constant. llvm::Constant *EmitNullConstantForBase(const CXXRecordDecl *Record); /// Emit a general error that something can't be done. void Error(SourceLocation loc, StringRef error); /// Print out an error that codegen doesn't support the specified stmt yet. void ErrorUnsupported(const Stmt *S, const char *Type); /// Print out an error that codegen doesn't support the specified decl yet. void ErrorUnsupported(const Decl *D, const char *Type); /// Set the attributes on the LLVM function for the given decl and function /// info. This applies attributes necessary for handling the ABI as well as /// user specified attributes like section. void SetInternalFunctionAttributes(const Decl *D, llvm::Function *F, const CGFunctionInfo &FI); /// Set the LLVM function attributes (sext, zext, etc). void SetLLVMFunctionAttributes(const Decl *D, const CGFunctionInfo &Info, llvm::Function *F); /// Set the LLVM function attributes which only apply to a function /// definition. void SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F); /// Return true iff the given type uses 'sret' when used as a return type. bool ReturnTypeUsesSRet(const CGFunctionInfo &FI); /// Return true iff the given type uses an argument slot when 'sret' is used /// as a return type. bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI); /// Return true iff the given type uses 'fpret' when used as a return type. bool ReturnTypeUsesFPRet(QualType ResultType); /// Return true iff the given type uses 'fp2ret' when used as a return type. bool ReturnTypeUsesFP2Ret(QualType ResultType); /// Get the LLVM attributes and calling convention to use for a particular /// function type. /// /// \param Name - The function name. /// \param Info - The function type information. /// \param CalleeInfo - The callee information these attributes are being /// constructed for. If valid, the attributes applied to this decl may /// contribute to the function attributes and calling convention. /// \param PAL [out] - On return, the attribute list to use. /// \param CallingConv [out] - On return, the LLVM calling convention to use. void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info, CGCalleeInfo CalleeInfo, AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite); // Fills in the supplied string map with the set of target features for the // passed in function. void getFunctionFeatureMap(llvm::StringMap &FeatureMap, const FunctionDecl *FD); StringRef getMangledName(GlobalDecl GD); StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD); void EmitTentativeDefinition(const VarDecl *D); void EmitVTable(CXXRecordDecl *Class); void RefreshTypeCacheForClass(const CXXRecordDecl *Class); /// \brief Appends Opts to the "Linker Options" metadata value. void AppendLinkerOptions(StringRef Opts); /// \brief Appends a detect mismatch command to the linker options. void AddDetectMismatch(StringRef Name, StringRef Value); /// \brief Appends a dependent lib to the "Linker Options" metadata value. void AddDependentLib(StringRef Lib); llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD); void setFunctionLinkage(GlobalDecl GD, llvm::Function *F) { F->setLinkage(getFunctionLinkage(GD)); } /// Set the DLL storage class on F. void setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F); /// Return the appropriate linkage for the vtable, VTT, and type information /// of the given class. llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD); /// Return the store size, in character units, of the given LLVM type. CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const; /// Returns LLVM linkage for a declarator. llvm::GlobalValue::LinkageTypes getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage, bool IsConstantVariable); /// Returns LLVM linkage for a declarator. llvm::GlobalValue::LinkageTypes getLLVMLinkageVarDefinition(const VarDecl *VD, bool IsConstant); /// Emit all the global annotations. void EmitGlobalAnnotations(); /// Emit an annotation string. llvm::Constant *EmitAnnotationString(StringRef Str); /// Emit the annotation's translation unit. llvm::Constant *EmitAnnotationUnit(SourceLocation Loc); /// Emit the annotation line number. llvm::Constant *EmitAnnotationLineNo(SourceLocation L); /// Generate the llvm::ConstantStruct which contains the annotation /// information for a given GlobalValue. The annotation struct is /// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the /// GlobalValue being annotated. The second field is the constant string /// created from the AnnotateAttr's annotation. The third field is a constant /// string containing the name of the translation unit. The fourth field is /// the line number in the file of the annotated value declaration. llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV, const AnnotateAttr *AA, SourceLocation L); /// Add global annotations that are set on D, for the global GV. Those /// annotations are emitted during finalization of the LLVM code. void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV); bool isInSanitizerBlacklist(llvm::Function *Fn, SourceLocation Loc) const; bool isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, StringRef Category = StringRef()) const; SanitizerMetadata *getSanitizerMetadata() { return SanitizerMD.get(); } void addDeferredVTable(const CXXRecordDecl *RD) { DeferredVTables.push_back(RD); } /// Emit code for a singal global function or var decl. Forward declarations /// are emitted lazily. void EmitGlobal(GlobalDecl D); bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target, bool InEveryTU); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); /// Set attributes for a global definition. void setFunctionDefinitionAttributes(const FunctionDecl *D, llvm::Function *F); llvm::GlobalValue *GetGlobalValue(StringRef Ref); /// Set attributes which are common to any form of a global definition (alias, /// Objective-C method, function, global variable). /// /// NOTE: This should only be called for definitions. void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV); /// Set attributes which must be preserved by an alias. This includes common /// attributes (i.e. it includes a call to SetCommonAttributes). /// /// NOTE: This should only be called for definitions. void setAliasAttributes(const Decl *D, llvm::GlobalValue *GV); void addReplacement(StringRef Name, llvm::Constant *C); void addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C); /// \brief Emit a code for threadprivate directive. /// \param D Threadprivate declaration. void EmitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *D); /// \brief Emit a code for declare reduction construct. void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D, CodeGenFunction *CGF = nullptr); /// Returns whether the given record has hidden LTO visibility and therefore /// may participate in (single-module) CFI and whole-program vtable /// optimization. bool HasHiddenLTOVisibility(const CXXRecordDecl *RD); /// Emit type metadata for the given vtable using the given layout. void EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, const VTableLayout &VTLayout); /// Generate a cross-DSO type identifier for MD. llvm::ConstantInt *CreateCrossDsoCfiTypeId(llvm::Metadata *MD); /// Create a metadata identifier for the given type. This may either be an /// MDString (for external identifiers) or a distinct unnamed MDNode (for /// internal identifiers). llvm::Metadata *CreateMetadataIdentifierForType(QualType T); /// Create and attach type metadata to the given function. void CreateFunctionTypeMetadata(const FunctionDecl *FD, llvm::Function *F); /// Returns whether this module needs the "all-vtables" type identifier. bool NeedAllVtablesTypeId() const; /// Create and attach type metadata for the given vtable. void AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD); /// \breif Get the declaration of std::terminate for the platform. llvm::Constant *getTerminateFn(); llvm::SanitizerStatReport &getSanStats(); llvm::Value * createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF); /// Get target specific null pointer. /// \param T is the LLVM type of the null pointer. /// \param QT is the clang QualType of the null pointer. llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT); private: llvm::Constant * GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable, bool DontDefer = false, bool IsThunk = false, llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(), ForDefinition_t IsForDefinition = NotForDefinition); llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName, llvm::PointerType *PTy, const VarDecl *D, ForDefinition_t IsForDefinition = NotForDefinition); void setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO); /// Set function attributes for a function declaration. void SetFunctionAttributes(GlobalDecl GD, llvm::Function *F, bool IsIncompleteFunction, bool IsThunk); void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr); void EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV); void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false); void EmitAliasDefinition(GlobalDecl GD); void emitIFuncDefinition(GlobalDecl GD); void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); void EmitObjCIvarInitializations(ObjCImplementationDecl *D); // C++ related functions. void EmitDeclContext(const DeclContext *DC); void EmitLinkageSpec(const LinkageSpecDecl *D); void CompleteDIClassType(const CXXMethodDecl* D); /// \brief Emit the function that initializes C++ thread_local variables. void EmitCXXThreadLocalInitFunc(); /// Emit the function that initializes C++ globals. void EmitCXXGlobalInitFunc(); /// Emit the function that destroys C++ globals. void EmitCXXGlobalDtorFunc(); /// Emit the function that initializes the specified global (if PerformInit is /// true) and registers its destructor. void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, llvm::GlobalVariable *Addr, bool PerformInit); void EmitPointerToInitFunc(const VarDecl *VD, llvm::GlobalVariable *Addr, llvm::Function *InitFunc, InitSegAttr *ISA); // FIXME: Hardcoding priority here is gross. void AddGlobalCtor(llvm::Function *Ctor, int Priority = 65535, llvm::Constant *AssociatedData = nullptr); void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535); /// EmitCtorList - Generates a global array of functions and priorities using /// the given list and name. This array will have appending linkage and is /// suitable for use as a LLVM constructor or destructor array. Clears Fns. void EmitCtorList(CtorList &Fns, const char *GlobalName); /// Emit any needed decls for which code generation was deferred. void EmitDeferred(); /// Call replaceAllUsesWith on all pairs in Replacements. void applyReplacements(); /// Call replaceAllUsesWith on all pairs in GlobalValReplacements. void applyGlobalValReplacements(); void checkAliases(); /// Emit any vtables which we deferred and still have a use for. void EmitDeferredVTables(); /// Emit the llvm.used and llvm.compiler.used metadata. void emitLLVMUsed(); /// \brief Emit the link options introduced by imported modules. void EmitModuleLinkOptions(); /// \brief Emit aliases for internal-linkage declarations inside "C" language /// linkage specifications, giving them the "expected" name where possible. void EmitStaticExternCAliases(); void EmitDeclMetadata(); /// \brief Emit the Clang version as llvm.ident metadata. void EmitVersionIdentMetadata(); /// Emits target specific Metadata for global declarations. void EmitTargetMetadata(); /// Emit the llvm.gcov metadata used to tell LLVM where to emit the .gcno and /// .gcda files in a way that persists in .bc files. void EmitCoverageFile(); /// Emits the initializer for a uuidof string. llvm::Constant *EmitUuidofInitializer(StringRef uuidstr); /// Determine whether the definition must be emitted; if this returns \c /// false, the definition can be emitted lazily if it's used. bool MustBeEmitted(const ValueDecl *D); /// Determine whether the definition can be emitted eagerly, or should be /// delayed until the end of the translation unit. This is relevant for /// definitions whose linkage can change, e.g. implicit function instantions /// which may later be explicitly instantiated. bool MayBeEmittedEagerly(const ValueDecl *D); /// Check whether we can use a "simpler", more core exceptions personality /// function. void SimplifyPersonality(); }; } // end namespace CodeGen } // end namespace clang #endif // LLVM_CLANG_LIB_CODEGEN_CODEGENMODULE_H Index: vendor/clang/dist/lib/Parse/ParseExpr.cpp =================================================================== --- vendor/clang/dist/lib/Parse/ParseExpr.cpp (revision 313882) +++ vendor/clang/dist/lib/Parse/ParseExpr.cpp (revision 313883) @@ -1,2998 +1,2998 @@ //===--- ParseExpr.cpp - Expression Parsing -------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// \brief Provides the Expression parsing implementation. /// /// Expressions in C99 basically consist of a bunch of binary operators with /// unary operators and other random stuff at the leaves. /// /// In the C99 grammar, these unary operators bind tightest and are represented /// as the 'cast-expression' production. Everything else is either a binary /// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are /// handled by ParseCastExpression, the higher level pieces are handled by /// ParseBinaryExpression. /// //===----------------------------------------------------------------------===// #include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Parse/Parser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/SmallVector.h" using namespace clang; /// \brief Simple precedence-based parser for binary/ternary operators. /// /// Note: we diverge from the C99 grammar when parsing the assignment-expression /// production. C99 specifies that the LHS of an assignment operator should be /// parsed as a unary-expression, but consistency dictates that it be a /// conditional-expession. In practice, the important thing here is that the /// LHS of an assignment has to be an l-value, which productions between /// unary-expression and conditional-expression don't produce. Because we want /// consistency, we parse the LHS as a conditional-expression, then check for /// l-value-ness in semantic analysis stages. /// /// \verbatim /// pm-expression: [C++ 5.5] /// cast-expression /// pm-expression '.*' cast-expression /// pm-expression '->*' cast-expression /// /// multiplicative-expression: [C99 6.5.5] /// Note: in C++, apply pm-expression instead of cast-expression /// cast-expression /// multiplicative-expression '*' cast-expression /// multiplicative-expression '/' cast-expression /// multiplicative-expression '%' cast-expression /// /// additive-expression: [C99 6.5.6] /// multiplicative-expression /// additive-expression '+' multiplicative-expression /// additive-expression '-' multiplicative-expression /// /// shift-expression: [C99 6.5.7] /// additive-expression /// shift-expression '<<' additive-expression /// shift-expression '>>' additive-expression /// /// relational-expression: [C99 6.5.8] /// shift-expression /// relational-expression '<' shift-expression /// relational-expression '>' shift-expression /// relational-expression '<=' shift-expression /// relational-expression '>=' shift-expression /// /// equality-expression: [C99 6.5.9] /// relational-expression /// equality-expression '==' relational-expression /// equality-expression '!=' relational-expression /// /// AND-expression: [C99 6.5.10] /// equality-expression /// AND-expression '&' equality-expression /// /// exclusive-OR-expression: [C99 6.5.11] /// AND-expression /// exclusive-OR-expression '^' AND-expression /// /// inclusive-OR-expression: [C99 6.5.12] /// exclusive-OR-expression /// inclusive-OR-expression '|' exclusive-OR-expression /// /// logical-AND-expression: [C99 6.5.13] /// inclusive-OR-expression /// logical-AND-expression '&&' inclusive-OR-expression /// /// logical-OR-expression: [C99 6.5.14] /// logical-AND-expression /// logical-OR-expression '||' logical-AND-expression /// /// conditional-expression: [C99 6.5.15] /// logical-OR-expression /// logical-OR-expression '?' expression ':' conditional-expression /// [GNU] logical-OR-expression '?' ':' conditional-expression /// [C++] the third operand is an assignment-expression /// /// assignment-expression: [C99 6.5.16] /// conditional-expression /// unary-expression assignment-operator assignment-expression /// [C++] throw-expression [C++ 15] /// /// assignment-operator: one of /// = *= /= %= += -= <<= >>= &= ^= |= /// /// expression: [C99 6.5.17] /// assignment-expression ...[opt] /// expression ',' assignment-expression ...[opt] /// \endverbatim ExprResult Parser::ParseExpression(TypeCastState isTypeCast) { ExprResult LHS(ParseAssignmentExpression(isTypeCast)); return ParseRHSOfBinaryExpression(LHS, prec::Comma); } /// This routine is called when the '@' is seen and consumed. /// Current token is an Identifier and is not a 'try'. This /// routine is necessary to disambiguate \@try-statement from, /// for example, \@encode-expression. /// ExprResult Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) { ExprResult LHS(ParseObjCAtExpression(AtLoc)); return ParseRHSOfBinaryExpression(LHS, prec::Comma); } /// This routine is called when a leading '__extension__' is seen and /// consumed. This is necessary because the token gets consumed in the /// process of disambiguating between an expression and a declaration. ExprResult Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { ExprResult LHS(true); { // Silence extension warnings in the sub-expression ExtensionRAIIObject O(Diags); LHS = ParseCastExpression(false); } if (!LHS.isInvalid()) LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__, LHS.get()); return ParseRHSOfBinaryExpression(LHS, prec::Comma); } /// \brief Parse an expr that doesn't include (top-level) commas. ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); cutOffParsing(); return ExprError(); } if (Tok.is(tok::kw_throw)) return ParseThrowExpression(); if (Tok.is(tok::kw_co_yield)) return ParseCoyieldExpression(); ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, isTypeCast); return ParseRHSOfBinaryExpression(LHS, prec::Assignment); } /// \brief Parse an assignment expression where part of an Objective-C message /// send has already been parsed. /// /// In this case \p LBracLoc indicates the location of the '[' of the message /// send, and either \p ReceiverName or \p ReceiverExpr is non-null indicating /// the receiver of the message. /// /// Since this handles full assignment-expression's, it handles postfix /// expressions and other binary operators for these expressions as well. ExprResult Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc, SourceLocation SuperLoc, ParsedType ReceiverType, Expr *ReceiverExpr) { ExprResult R = ParseObjCMessageExpressionBody(LBracLoc, SuperLoc, ReceiverType, ReceiverExpr); R = ParsePostfixExpressionSuffix(R); return ParseRHSOfBinaryExpression(R, prec::Assignment); } ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { // C++03 [basic.def.odr]p2: // An expression is potentially evaluated unless it appears where an // integral constant expression is required (see 5.19) [...]. // C++98 and C++11 have no such rule, but this is only a defect in C++98. EnterExpressionEvaluationContext ConstantEvaluated(Actions, Sema::ConstantEvaluated); ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); return Actions.ActOnConstantExpression(Res); } /// \brief Parse a constraint-expression. /// /// \verbatim /// constraint-expression: [Concepts TS temp.constr.decl p1] /// logical-or-expression /// \endverbatim ExprResult Parser::ParseConstraintExpression() { // FIXME: this may erroneously consume a function-body as the braced // initializer list of a compound literal // // FIXME: this may erroneously consume a parenthesized rvalue reference // declarator as a parenthesized address-of-label expression ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); return Res; } bool Parser::isNotExpressionStart() { tok::TokenKind K = Tok.getKind(); if (K == tok::l_brace || K == tok::r_brace || K == tok::kw_for || K == tok::kw_while || K == tok::kw_if || K == tok::kw_else || K == tok::kw_goto || K == tok::kw_try) return true; // If this is a decl-specifier, we can't be at the start of an expression. return isKnownToBeDeclarationSpecifier(); } static bool isFoldOperator(prec::Level Level) { return Level > prec::Unknown && Level != prec::Conditional; } static bool isFoldOperator(tok::TokenKind Kind) { return isFoldOperator(getBinOpPrecedence(Kind, false, true)); } /// \brief Parse a binary expression that starts with \p LHS and has a /// precedence of at least \p MinPrec. ExprResult Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, getLangOpts().CPlusPlus11); SourceLocation ColonLoc; while (1) { // If this token has a lower precedence than we are allowed to parse (e.g. // because we are called recursively, or because the token is not a binop), // then we are done! if (NextTokPrec < MinPrec) return LHS; // Consume the operator, saving the operator token for error reporting. Token OpToken = Tok; ConsumeToken(); if (OpToken.is(tok::caretcaret)) { return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or)); } // Bail out when encountering a comma followed by a token which can't // possibly be the start of an expression. For instance: // int f() { return 1, } // We can't do this before consuming the comma, because // isNotExpressionStart() looks at the token stream. if (OpToken.is(tok::comma) && isNotExpressionStart()) { PP.EnterToken(Tok); Tok = OpToken; return LHS; } // If the next token is an ellipsis, then this is a fold-expression. Leave // it alone so we can handle it in the paren expression. if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { // FIXME: We can't check this via lookahead before we consume the token // because that tickles a lexer bug. PP.EnterToken(Tok); Tok = OpToken; return LHS; } // Special case handling for the ternary operator. ExprResult TernaryMiddle(true); if (NextTokPrec == prec::Conditional) { if (Tok.isNot(tok::colon)) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR. ColonProtectionRAIIObject X(*this); // Handle this production specially: // logical-OR-expression '?' expression ':' conditional-expression // In particular, the RHS of the '?' is 'expression', not // 'logical-OR-expression' as we might expect. TernaryMiddle = ParseExpression(); if (TernaryMiddle.isInvalid()) { Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); TernaryMiddle = nullptr; } } else { // Special case handling of "X ? Y : Z" where Y is empty: // logical-OR-expression '?' ':' conditional-expression [GNU] TernaryMiddle = nullptr; Diag(Tok, diag::ext_gnu_conditional_expr); } if (!TryConsumeToken(tok::colon, ColonLoc)) { // Otherwise, we're missing a ':'. Assume that this was a typo that // the user forgot. If we're not in a macro expansion, we can suggest // a fixit hint. If there were two spaces before the current token, // suggest inserting the colon in between them, otherwise insert ": ". SourceLocation FILoc = Tok.getLocation(); const char *FIText = ": "; const SourceManager &SM = PP.getSourceManager(); if (FILoc.isFileID() || PP.isAtStartOfMacroExpansion(FILoc, &FILoc)) { assert(FILoc.isFileID()); bool IsInvalid = false; const char *SourcePtr = SM.getCharacterData(FILoc.getLocWithOffset(-1), &IsInvalid); if (!IsInvalid && *SourcePtr == ' ') { SourcePtr = SM.getCharacterData(FILoc.getLocWithOffset(-2), &IsInvalid); if (!IsInvalid && *SourcePtr == ' ') { FILoc = FILoc.getLocWithOffset(-1); FIText = ":"; } } } Diag(Tok, diag::err_expected) << tok::colon << FixItHint::CreateInsertion(FILoc, FIText); Diag(OpToken, diag::note_matching) << tok::question; ColonLoc = Tok.getLocation(); } } // Code completion for the right-hand side of an assignment expression // goes through a special hook that takes the left-hand side into account. if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) { Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get()); cutOffParsing(); return ExprError(); } // Parse another leaf here for the RHS of the operator. // ParseCastExpression works here because all RHS expressions in C have it // as a prefix, at least. However, in C++, an assignment-expression could // be a throw-expression, which is not a valid cast-expression. // Therefore we need some special-casing here. // Also note that the third operand of the conditional operator is // an assignment-expression in C++, and in C++11, we can have a // braced-init-list on the RHS of an assignment. For better diagnostics, // parse as if we were allowed braced-init-lists everywhere, and check that // they only appear on the RHS of assignments later. ExprResult RHS; bool RHSIsInitList = false; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { RHS = ParseBraceInitializer(); RHSIsInitList = true; } else if (getLangOpts().CPlusPlus && NextTokPrec <= prec::Conditional) RHS = ParseAssignmentExpression(); else RHS = ParseCastExpression(false); if (RHS.isInvalid()) { // FIXME: Errors generated by the delayed typo correction should be // printed before errors from parsing the RHS, not after. Actions.CorrectDelayedTyposInExpr(LHS); if (TernaryMiddle.isUsable()) TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle); LHS = ExprError(); } // Remember the precedence of this operator and get the precedence of the // operator immediately to the right of the RHS. prec::Level ThisPrec = NextTokPrec; NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, getLangOpts().CPlusPlus11); // Assignment and conditional expressions are right-associative. bool isRightAssoc = ThisPrec == prec::Conditional || ThisPrec == prec::Assignment; // Get the precedence of the operator to the right of the RHS. If it binds // more tightly with RHS than we do, evaluate it completely first. if (ThisPrec < NextTokPrec || (ThisPrec == NextTokPrec && isRightAssoc)) { if (!RHS.isInvalid() && RHSIsInitList) { Diag(Tok, diag::err_init_list_bin_op) << /*LHS*/0 << PP.getSpelling(Tok) << Actions.getExprRange(RHS.get()); RHS = ExprError(); } // If this is left-associative, only parse things on the RHS that bind // more tightly than the current operator. If it is left-associative, it // is okay, to bind exactly as tightly. For example, compile A=B=C=D as // A=(B=(C=D)), where each paren is a level of recursion here. // The function takes ownership of the RHS. RHS = ParseRHSOfBinaryExpression(RHS, static_cast(ThisPrec + !isRightAssoc)); RHSIsInitList = false; if (RHS.isInvalid()) { // FIXME: Errors generated by the delayed typo correction should be // printed before errors from ParseRHSOfBinaryExpression, not after. Actions.CorrectDelayedTyposInExpr(LHS); if (TernaryMiddle.isUsable()) TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle); LHS = ExprError(); } NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator, getLangOpts().CPlusPlus11); } if (!RHS.isInvalid() && RHSIsInitList) { if (ThisPrec == prec::Assignment) { Diag(OpToken, diag::warn_cxx98_compat_generalized_initializer_lists) << Actions.getExprRange(RHS.get()); } else { Diag(OpToken, diag::err_init_list_bin_op) << /*RHS*/1 << PP.getSpelling(OpToken) << Actions.getExprRange(RHS.get()); LHS = ExprError(); } } ExprResult OrigLHS = LHS; if (!LHS.isInvalid()) { // Combine the LHS and RHS into the LHS (e.g. build AST). if (TernaryMiddle.isInvalid()) { // If we're using '>>' as an operator within a template // argument list (in C++98), suggest the addition of // parentheses so that the code remains well-formed in C++0x. if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater)) SuggestParentheses(OpToken.getLocation(), diag::warn_cxx11_right_shift_in_template_arg, SourceRange(Actions.getExprRange(LHS.get()).getBegin(), Actions.getExprRange(RHS.get()).getEnd())); LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(), OpToken.getKind(), LHS.get(), RHS.get()); } else { LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc, LHS.get(), TernaryMiddle.get(), RHS.get()); } // In this case, ActOnBinOp or ActOnConditionalOp performed the // CorrectDelayedTyposInExpr check. if (!getLangOpts().CPlusPlus) continue; } // Ensure potential typos aren't left undiagnosed. if (LHS.isInvalid()) { Actions.CorrectDelayedTyposInExpr(OrigLHS); Actions.CorrectDelayedTyposInExpr(TernaryMiddle); Actions.CorrectDelayedTyposInExpr(RHS); } } } /// \brief Parse a cast-expression, or, if \p isUnaryExpression is true, /// parse a unary-expression. /// /// \p isAddressOfOperand exists because an id-expression that is the /// operand of address-of gets special treatment due to member pointers. /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, TypeCastState isTypeCast) { bool NotCastExpr; ExprResult Res = ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); if (NotCastExpr) Diag(Tok, diag::err_expected_expression); return Res; } namespace { class CastExpressionIdValidator : public CorrectionCandidateCallback { public: CastExpressionIdValidator(Token Next, bool AllowTypes, bool AllowNonTypes) : NextToken(Next), AllowNonTypes(AllowNonTypes) { WantTypeSpecifiers = WantFunctionLikeCasts = AllowTypes; } bool ValidateCandidate(const TypoCorrection &candidate) override { NamedDecl *ND = candidate.getCorrectionDecl(); if (!ND) return candidate.isKeyword(); if (isa(ND)) return WantTypeSpecifiers; if (!AllowNonTypes || !CorrectionCandidateCallback::ValidateCandidate(candidate)) return false; if (!NextToken.isOneOf(tok::equal, tok::arrow, tok::period)) return true; for (auto *C : candidate) { NamedDecl *ND = C->getUnderlyingDecl(); if (isa(ND) && !isa(ND)) return true; } return false; } private: Token NextToken; bool AllowNonTypes; }; } /// \brief Parse a cast-expression, or, if \pisUnaryExpression is true, parse /// a unary-expression. /// /// \p isAddressOfOperand exists because an id-expression that is the operand /// of address-of gets special treatment due to member pointers. NotCastExpr /// is set to true if the token is not the start of a cast-expression, and no /// diagnostic is emitted in this case and no tokens are consumed. /// /// \verbatim /// cast-expression: [C99 6.5.4] /// unary-expression /// '(' type-name ')' cast-expression /// /// unary-expression: [C99 6.5.3] /// postfix-expression /// '++' unary-expression /// '--' unary-expression /// [Coro] 'co_await' cast-expression /// unary-operator cast-expression /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' /// [C++11] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C11] '_Alignof' '(' type-name ')' /// [C++11] 'alignof' '(' type-id ')' /// [GNU] '&&' identifier /// [C++11] 'noexcept' '(' expression ')' [C++11 5.3.7] /// [C++] new-expression /// [C++] delete-expression /// /// unary-operator: one of /// '&' '*' '+' '-' '~' '!' /// [GNU] '__extension__' '__real' '__imag' /// /// primary-expression: [C99 6.5.1] /// [C99] identifier /// [C++] id-expression /// constant /// string-literal /// [C++] boolean-literal [C++ 2.13.5] /// [C++11] 'nullptr' [C++11 2.14.7] /// [C++11] user-defined-literal /// '(' expression ')' /// [C11] generic-selection /// '__func__' [C99 6.4.2.2] /// [GNU] '__FUNCTION__' /// [MS] '__FUNCDNAME__' /// [MS] 'L__FUNCTION__' /// [GNU] '__PRETTY_FUNCTION__' /// [GNU] '(' compound-statement ')' /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')' /// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')' /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ',' /// assign-expr ')' /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')' /// [GNU] '__null' /// [OBJC] '[' objc-message-expr ']' /// [OBJC] '\@selector' '(' objc-selector-arg ')' /// [OBJC] '\@protocol' '(' identifier ')' /// [OBJC] '\@encode' '(' type-name ')' /// [OBJC] objc-string-literal /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] /// [C++11] simple-type-specifier braced-init-list [C++11 5.2.3] /// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3] /// [C++11] typename-specifier braced-init-list [C++11 5.2.3] /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'typeid' '(' expression ')' [C++ 5.2p1] /// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1] /// [C++] 'this' [C++ 9.3.2] /// [G++] unary-type-trait '(' type-id ')' /// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO] /// [EMBT] array-type-trait '(' type-id ',' integer ')' /// [clang] '^' block-literal /// /// constant: [C99 6.4.4] /// integer-constant /// floating-constant /// enumeration-constant -> identifier /// character-constant /// /// id-expression: [C++ 5.1] /// unqualified-id /// qualified-id /// /// unqualified-id: [C++ 5.1] /// identifier /// operator-function-id /// conversion-function-id /// '~' class-name /// template-id /// /// new-expression: [C++ 5.3.4] /// '::'[opt] 'new' new-placement[opt] new-type-id /// new-initializer[opt] /// '::'[opt] 'new' new-placement[opt] '(' type-id ')' /// new-initializer[opt] /// /// delete-expression: [C++ 5.3.5] /// '::'[opt] 'delete' cast-expression /// '::'[opt] 'delete' '[' ']' cast-expression /// /// [GNU/Embarcadero] unary-type-trait: /// '__is_arithmetic' /// '__is_floating_point' /// '__is_integral' /// '__is_lvalue_expr' /// '__is_rvalue_expr' /// '__is_complete_type' /// '__is_void' /// '__is_array' /// '__is_function' /// '__is_reference' /// '__is_lvalue_reference' /// '__is_rvalue_reference' /// '__is_fundamental' /// '__is_object' /// '__is_scalar' /// '__is_compound' /// '__is_pointer' /// '__is_member_object_pointer' /// '__is_member_function_pointer' /// '__is_member_pointer' /// '__is_const' /// '__is_volatile' /// '__is_trivial' /// '__is_standard_layout' /// '__is_signed' /// '__is_unsigned' /// /// [GNU] unary-type-trait: /// '__has_nothrow_assign' /// '__has_nothrow_copy' /// '__has_nothrow_constructor' /// '__has_trivial_assign' [TODO] /// '__has_trivial_copy' [TODO] /// '__has_trivial_constructor' /// '__has_trivial_destructor' /// '__has_virtual_destructor' /// '__is_abstract' [TODO] /// '__is_class' /// '__is_empty' [TODO] /// '__is_enum' /// '__is_final' /// '__is_pod' /// '__is_polymorphic' /// '__is_sealed' [MS] /// '__is_trivial' /// '__is_union' /// /// [Clang] unary-type-trait: /// '__trivially_copyable' /// /// binary-type-trait: /// [GNU] '__is_base_of' /// [MS] '__is_convertible_to' /// '__is_convertible' /// '__is_same' /// /// [Embarcadero] array-type-trait: /// '__array_rank' /// '__array_extent' /// /// [Embarcadero] expression-trait: /// '__is_lvalue_expr' /// '__is_rvalue_expr' /// \endverbatim /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool &NotCastExpr, TypeCastState isTypeCast) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); NotCastExpr = false; // This handles all of cast-expression, unary-expression, postfix-expression, // and primary-expression. We handle them together like this for efficiency // and to simplify handling of an expression starting with a '(' token: which // may be one of a parenthesized expression, cast-expression, compound literal // expression, or statement expression. // // If the parsed tokens consist of a primary-expression, the cases below // break out of the switch; at the end we call ParsePostfixExpressionSuffix // to handle the postfix expression suffixes. Cases that cannot be followed // by postfix exprs should return without invoking // ParsePostfixExpressionSuffix. switch (SavedKind) { case tok::l_paren: { // If this expression is limited to being a unary-expression, the parent can // not start a cast expression. ParenParseOption ParenExprType = (isUnaryExpression && !getLangOpts().CPlusPlus) ? CompoundLiteral : CastExpr; ParsedType CastTy; SourceLocation RParenLoc; Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/, isTypeCast == IsTypeCast, CastTy, RParenLoc); switch (ParenExprType) { case SimpleExpr: break; // Nothing else to do. case CompoundStmt: break; // Nothing else to do. case CompoundLiteral: // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of // postfix-expression exist, parse them now. break; case CastExpr: // We have parsed the cast-expression and no postfix-expr pieces are // following. return Res; } break; } // primary-expression case tok::numeric_constant: // constant: integer-constant // constant: floating-constant Res = Actions.ActOnNumericConstant(Tok, /*UDLScope*/getCurScope()); ConsumeToken(); break; case tok::kw_true: case tok::kw_false: return ParseCXXBoolLiteral(); case tok::kw___objc_yes: case tok::kw___objc_no: return ParseObjCBoolLiteral(); case tok::kw_nullptr: Diag(Tok, diag::warn_cxx98_compat_nullptr); return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); case tok::annot_primary_expr: assert(Res.get() == nullptr && "Stray primary-expression annotation?"); Res = getExprAnnotation(Tok); ConsumeToken(); break; case tok::kw___super: case tok::kw_decltype: // Annotate the token and tail recurse. if (TryAnnotateTypeOrScopeToken()) return ExprError(); assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super)); return ParseCastExpression(isUnaryExpression, isAddressOfOperand); case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant // Turn a potentially qualified name into a annot_typename or // annot_cxxscope if it would be valid. This handles things like x::y, etc. if (getLangOpts().CPlusPlus) { // Avoid the unnecessary parse-time lookup in the common case // where the syntax forbids a type. const Token &Next = NextToken(); // If this identifier was reverted from a token ID, and the next token // is a parenthesis, this is likely to be a use of a type trait. Check // those tokens. if (Next.is(tok::l_paren) && Tok.is(tok::identifier) && Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier()) { IdentifierInfo *II = Tok.getIdentifierInfo(); // Build up the mapping of revertible type traits, for future use. if (RevertibleTypeTraits.empty()) { #define RTT_JOIN(X,Y) X##Y #define REVERTIBLE_TYPE_TRAIT(Name) \ RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] \ = RTT_JOIN(tok::kw_,Name) REVERTIBLE_TYPE_TRAIT(__is_abstract); REVERTIBLE_TYPE_TRAIT(__is_arithmetic); REVERTIBLE_TYPE_TRAIT(__is_array); REVERTIBLE_TYPE_TRAIT(__is_assignable); REVERTIBLE_TYPE_TRAIT(__is_base_of); REVERTIBLE_TYPE_TRAIT(__is_class); REVERTIBLE_TYPE_TRAIT(__is_complete_type); REVERTIBLE_TYPE_TRAIT(__is_compound); REVERTIBLE_TYPE_TRAIT(__is_const); REVERTIBLE_TYPE_TRAIT(__is_constructible); REVERTIBLE_TYPE_TRAIT(__is_convertible); REVERTIBLE_TYPE_TRAIT(__is_convertible_to); REVERTIBLE_TYPE_TRAIT(__is_destructible); REVERTIBLE_TYPE_TRAIT(__is_empty); REVERTIBLE_TYPE_TRAIT(__is_enum); REVERTIBLE_TYPE_TRAIT(__is_floating_point); REVERTIBLE_TYPE_TRAIT(__is_final); REVERTIBLE_TYPE_TRAIT(__is_function); REVERTIBLE_TYPE_TRAIT(__is_fundamental); REVERTIBLE_TYPE_TRAIT(__is_integral); REVERTIBLE_TYPE_TRAIT(__is_interface_class); REVERTIBLE_TYPE_TRAIT(__is_literal); REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr); REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference); REVERTIBLE_TYPE_TRAIT(__is_member_function_pointer); REVERTIBLE_TYPE_TRAIT(__is_member_object_pointer); REVERTIBLE_TYPE_TRAIT(__is_member_pointer); REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable); REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible); REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible); REVERTIBLE_TYPE_TRAIT(__is_object); REVERTIBLE_TYPE_TRAIT(__is_pod); REVERTIBLE_TYPE_TRAIT(__is_pointer); REVERTIBLE_TYPE_TRAIT(__is_polymorphic); REVERTIBLE_TYPE_TRAIT(__is_reference); REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr); REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference); REVERTIBLE_TYPE_TRAIT(__is_same); REVERTIBLE_TYPE_TRAIT(__is_scalar); REVERTIBLE_TYPE_TRAIT(__is_sealed); REVERTIBLE_TYPE_TRAIT(__is_signed); REVERTIBLE_TYPE_TRAIT(__is_standard_layout); REVERTIBLE_TYPE_TRAIT(__is_trivial); REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable); REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible); REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable); REVERTIBLE_TYPE_TRAIT(__is_union); REVERTIBLE_TYPE_TRAIT(__is_unsigned); REVERTIBLE_TYPE_TRAIT(__is_void); REVERTIBLE_TYPE_TRAIT(__is_volatile); #undef REVERTIBLE_TYPE_TRAIT #undef RTT_JOIN } // If we find that this is in fact the name of a type trait, // update the token kind in place and parse again to treat it as // the appropriate kind of type trait. llvm::SmallDenseMap::iterator Known = RevertibleTypeTraits.find(II); if (Known != RevertibleTypeTraits.end()) { Tok.setKind(Known->second); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); } } if ((!ColonIsSacred && Next.is(tok::colon)) || Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren, tok::l_brace)) { // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse. if (TryAnnotateTypeOrScopeToken()) return ExprError(); if (!Tok.is(tok::identifier)) return ParseCastExpression(isUnaryExpression, isAddressOfOperand); } } // Consume the identifier so that we can see if it is followed by a '(' or // '.'. IdentifierInfo &II = *Tok.getIdentifierInfo(); SourceLocation ILoc = ConsumeToken(); // Support 'Class.property' and 'super.property' notation. if (getLangOpts().ObjC1 && Tok.is(tok::period) && (Actions.getTypeName(II, ILoc, getCurScope()) || // Allow the base to be 'super' if in an objc-method. (&II == Ident_super && getCurScope()->isInObjcMethodScope()))) { ConsumeToken(); if (Tok.is(tok::code_completion) && &II != Ident_super) { Actions.CodeCompleteObjCClassPropertyRefExpr( getCurScope(), II, ILoc, ExprStatementTokLoc == ILoc); cutOffParsing(); return ExprError(); } // Allow either an identifier or the keyword 'class' (in C++). if (Tok.isNot(tok::identifier) && !(getLangOpts().CPlusPlus && Tok.is(tok::kw_class))) { Diag(Tok, diag::err_expected_property_name); return ExprError(); } IdentifierInfo &PropertyName = *Tok.getIdentifierInfo(); SourceLocation PropertyLoc = ConsumeToken(); Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName, ILoc, PropertyLoc); break; } // In an Objective-C method, if we have "super" followed by an identifier, // the token sequence is ill-formed. However, if there's a ':' or ']' after // that identifier, this is probably a message send with a missing open // bracket. Treat it as such. if (getLangOpts().ObjC1 && &II == Ident_super && !InMessageExpression && getCurScope()->isInObjcMethodScope() && ((Tok.is(tok::identifier) && (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) || Tok.is(tok::code_completion))) { Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, nullptr, nullptr); break; } // If we have an Objective-C class name followed by an identifier // and either ':' or ']', this is an Objective-C class message // send that's missing the opening '['. Recovery // appropriately. Also take this path if we're performing code // completion after an Objective-C class name. if (getLangOpts().ObjC1 && ((Tok.is(tok::identifier) && !InMessageExpression) || Tok.is(tok::code_completion))) { const Token& Next = NextToken(); if (Tok.is(tok::code_completion) || Next.is(tok::colon) || Next.is(tok::r_square)) if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope())) if (Typ.get()->isObjCObjectOrInterfaceType()) { // Fake up a Declarator to use with ActOnTypeName. DeclSpec DS(AttrFactory); DS.SetRangeStart(ILoc); DS.SetRangeEnd(ILoc); const char *PrevSpec = nullptr; unsigned DiagID; DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ, Actions.getASTContext().getPrintingPolicy()); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) break; Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), Ty.get(), nullptr); break; } } // Make sure to pass down the right value for isAddressOfOperand. if (isAddressOfOperand && isPostfixExpressionSuffixStart()) isAddressOfOperand = false; // Function designators are allowed to be undeclared (C99 6.5.1p2), so we // need to know whether or not this identifier is a function designator or // not. UnqualifiedId Name; CXXScopeSpec ScopeSpec; SourceLocation TemplateKWLoc; Token Replacement; auto Validator = llvm::make_unique( Tok, isTypeCast != NotTypeCast, isTypeCast != IsTypeCast); Validator->IsAddressOfOperand = isAddressOfOperand; if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) { Validator->WantExpressionKeywords = false; Validator->WantRemainingKeywords = false; } else { Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren); } Name.setIdentifier(&II, ILoc); Res = Actions.ActOnIdExpression( getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren), isAddressOfOperand, std::move(Validator), /*IsInlineAsmIdentifier=*/false, Tok.is(tok::r_paren) ? nullptr : &Replacement); if (!Res.isInvalid() && !Res.get()) { UnconsumeToken(Replacement); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); } break; } case tok::char_constant: // constant: character-constant case tok::wide_char_constant: case tok::utf8_char_constant: case tok::utf16_char_constant: case tok::utf32_char_constant: Res = Actions.ActOnCharacterConstant(Tok, /*UDLScope*/getCurScope()); ConsumeToken(); break; case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2] case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU] case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS] case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS] case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS] case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU] Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); ConsumeToken(); break; case tok::string_literal: // primary-expression: string-literal case tok::wide_string_literal: case tok::utf8_string_literal: case tok::utf16_string_literal: case tok::utf32_string_literal: Res = ParseStringLiteralExpression(true); break; case tok::kw__Generic: // primary-expression: generic-selection [C11 6.5.1] Res = ParseGenericSelectionExpression(); break; case tok::kw___builtin_available: return ParseAvailabilityCheckExpr(Tok.getLocation()); case tok::kw___builtin_va_arg: case tok::kw___builtin_offsetof: case tok::kw___builtin_choose_expr: case tok::kw___builtin_astype: // primary-expression: [OCL] as_type() case tok::kw___builtin_convertvector: return ParseBuiltinPrimaryExpression(); case tok::kw___null: return Actions.ActOnGNUNullExpr(ConsumeToken()); case tok::plusplus: // unary-expression: '++' unary-expression [C99] case tok::minusminus: { // unary-expression: '--' unary-expression [C99] // C++ [expr.unary] has: // unary-expression: // ++ cast-expression // -- cast-expression Token SavedTok = Tok; ConsumeToken(); // One special case is implicitly handled here: if the preceding tokens are // an ambiguous cast expression, such as "(T())++", then we recurse to // determine whether the '++' is prefix or postfix. Res = ParseCastExpression(!getLangOpts().CPlusPlus, /*isAddressOfOperand*/false, NotCastExpr, NotTypeCast); if (NotCastExpr) { // If we return with NotCastExpr = true, we must not consume any tokens, // so put the token back where we found it. assert(Res.isInvalid()); UnconsumeToken(SavedTok); return ExprError(); } if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedTok.getLocation(), SavedKind, Res.get()); return Res; } case tok::amp: { // unary-expression: '&' cast-expression // Special treatment because of member pointers SourceLocation SavedLoc = ConsumeToken(); Res = ParseCastExpression(false, true); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return Res; } case tok::star: // unary-expression: '*' cast-expression case tok::plus: // unary-expression: '+' cast-expression case tok::minus: // unary-expression: '-' cast-expression case tok::tilde: // unary-expression: '~' cast-expression case tok::exclaim: // unary-expression: '!' cast-expression case tok::kw___real: // unary-expression: '__real' cast-expression [GNU] case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU] SourceLocation SavedLoc = ConsumeToken(); Res = ParseCastExpression(false); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return Res; } case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression SourceLocation CoawaitLoc = ConsumeToken(); Res = ParseCastExpression(false); if (!Res.isInvalid()) Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get()); return Res; } case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU] // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. SourceLocation SavedLoc = ConsumeToken(); Res = ParseCastExpression(false); if (!Res.isInvalid()) Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return Res; } case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')' if (!getLangOpts().C11) Diag(Tok, diag::ext_c11_alignment) << Tok.getName(); // fallthrough case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')' case tok::kw___alignof: // unary-expression: '__alignof' unary-expression // unary-expression: '__alignof' '(' type-name ')' case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression // unary-expression: 'sizeof' '(' type-name ')' case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')' case tok::kw___builtin_omp_required_simd_align: return ParseUnaryExprOrTypeTraitExpression(); case tok::ampamp: { // unary-expression: '&&' identifier SourceLocation AmpAmpLoc = ConsumeToken(); if (Tok.isNot(tok::identifier)) return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); if (getCurScope()->getFnParent() == nullptr) return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn)); Diag(AmpAmpLoc, diag::ext_gnu_address_of_label); LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(), Tok.getLocation()); Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD); ConsumeToken(); return Res; } case tok::kw_const_cast: case tok::kw_dynamic_cast: case tok::kw_reinterpret_cast: case tok::kw_static_cast: Res = ParseCXXCasts(); break; case tok::kw_typeid: Res = ParseCXXTypeid(); break; case tok::kw___uuidof: Res = ParseCXXUuidof(); break; case tok::kw_this: Res = ParseCXXThis(); break; case tok::annot_typename: if (isStartOfObjCClassMessageMissingOpenBracket()) { ParsedType Type = getTypeAnnotation(Tok); // Fake up a Declarator to use with ActOnTypeName. DeclSpec DS(AttrFactory); DS.SetRangeStart(Tok.getLocation()); DS.SetRangeEnd(Tok.getLastLoc()); const char *PrevSpec = nullptr; unsigned DiagID; DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(), PrevSpec, DiagID, Type, Actions.getASTContext().getPrintingPolicy()); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) break; ConsumeToken(); Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), Ty.get(), nullptr); break; } // Fall through case tok::annot_decltype: case tok::kw_char: case tok::kw_wchar_t: case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_bool: case tok::kw_short: case tok::kw_int: case tok::kw_long: case tok::kw___int64: case tok::kw___int128: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw___float128: case tok::kw_void: case tok::kw_typename: case tok::kw_typeof: case tok::kw___vector: #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" { if (!getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_expression); return ExprError(); } if (SavedKind == tok::kw_typename) { // postfix-expression: typename-specifier '(' expression-list[opt] ')' // typename-specifier braced-init-list if (TryAnnotateTypeOrScopeToken()) return ExprError(); if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) // We are trying to parse a simple-type-specifier but might not get such // a token after error recovery. return ExprError(); } // postfix-expression: simple-type-specifier '(' expression-list[opt] ')' // simple-type-specifier braced-init-list // DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); if (Tok.isNot(tok::l_paren) && (!getLangOpts().CPlusPlus11 || Tok.isNot(tok::l_brace))) return ExprError(Diag(Tok, diag::err_expected_lparen_after_type) << DS.getSourceRange()); if (Tok.is(tok::l_brace)) Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Res = ParseCXXTypeConstructExpression(DS); break; } case tok::annot_cxxscope: { // [C++] id-expression: qualified-id // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse. // (We can end up in this situation after tentative parsing.) if (TryAnnotateTypeOrScopeToken()) return ExprError(); if (!Tok.is(tok::annot_cxxscope)) return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); Token Next = NextToken(); if (Next.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next); if (TemplateId->Kind == TNK_Type_template) { // We have a qualified template-id that we know refers to a // type, translate it into a type and continue parsing as a // cast expression. CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); AnnotateTemplateIdTokenAsType(); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); } } // Parse as an id-expression. Res = ParseCXXIdExpression(isAddressOfOperand); break; } case tok::annot_template_id: { // [C++] template-id TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->Kind == TNK_Type_template) { // We have a template-id that we know refers to a type, // translate it into a type and continue parsing as a cast // expression. AnnotateTemplateIdTokenAsType(); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); } // Fall through to treat the template-id as an id-expression. } case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id Res = ParseCXXIdExpression(isAddressOfOperand); break; case tok::coloncolon: { // ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken // annotates the token, tail recurse. if (TryAnnotateTypeOrScopeToken()) return ExprError(); if (!Tok.is(tok::coloncolon)) return ParseCastExpression(isUnaryExpression, isAddressOfOperand); // ::new -> [C++] new-expression // ::delete -> [C++] delete-expression SourceLocation CCLoc = ConsumeToken(); if (Tok.is(tok::kw_new)) return ParseCXXNewExpression(true, CCLoc); if (Tok.is(tok::kw_delete)) return ParseCXXDeleteExpression(true, CCLoc); // This is not a type name or scope specifier, it is an invalid expression. Diag(CCLoc, diag::err_expected_expression); return ExprError(); } case tok::kw_new: // [C++] new-expression return ParseCXXNewExpression(false, Tok.getLocation()); case tok::kw_delete: // [C++] delete-expression return ParseCXXDeleteExpression(false, Tok.getLocation()); case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')' Diag(Tok, diag::warn_cxx98_compat_noexcept_expr); SourceLocation KeyLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.expectAndConsume(diag::err_expected_lparen_after, "noexcept")) return ExprError(); // C++11 [expr.unary.noexcept]p1: // The noexcept operator determines whether the evaluation of its operand, // which is an unevaluated operand, can throw an exception. EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); ExprResult Result = ParseExpression(); T.consumeClose(); if (!Result.isInvalid()) Result = Actions.ActOnNoexceptExpr(KeyLoc, T.getOpenLocation(), Result.get(), T.getCloseLocation()); return Result; } #define TYPE_TRAIT(N,Spelling,K) \ case tok::kw_##Spelling: #include "clang/Basic/TokenKinds.def" return ParseTypeTrait(); case tok::kw___array_rank: case tok::kw___array_extent: return ParseArrayTypeTrait(); case tok::kw___is_lvalue_expr: case tok::kw___is_rvalue_expr: return ParseExpressionTrait(); case tok::at: { SourceLocation AtLoc = ConsumeToken(); return ParseObjCAtExpression(AtLoc); } case tok::caret: Res = ParseBlockLiteralExpression(); break; case tok::code_completion: { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); cutOffParsing(); return ExprError(); } case tok::l_square: if (getLangOpts().CPlusPlus11) { if (getLangOpts().ObjC1) { // C++11 lambda expressions and Objective-C message sends both start with a // square bracket. There are three possibilities here: // we have a valid lambda expression, we have an invalid lambda // expression, or we have something that doesn't appear to be a lambda. // If we're in the last case, we fall back to ParseObjCMessageExpression. Res = TryParseLambdaExpression(); if (!Res.isInvalid() && !Res.get()) Res = ParseObjCMessageExpression(); break; } Res = ParseLambdaExpression(); break; } if (getLangOpts().ObjC1) { Res = ParseObjCMessageExpression(); break; } // FALL THROUGH. default: NotCastExpr = true; return ExprError(); } // Check to see whether Res is a function designator only. If it is and we // are compiling for OpenCL, we need to return an error as this implies // that the address of the function is being taken, which is illegal in CL. // These can be followed by postfix-expr pieces. Res = ParsePostfixExpressionSuffix(Res); if (getLangOpts().OpenCL) if (Expr *PostfixExpr = Res.get()) { QualType Ty = PostfixExpr->getType(); if (!Ty.isNull() && Ty->isFunctionType()) { Diag(PostfixExpr->getExprLoc(), diag::err_opencl_taking_function_address_parser); return ExprError(); } } return Res; } /// \brief Once the leading part of a postfix-expression is parsed, this /// method parses any suffixes that apply. /// /// \verbatim /// postfix-expression: [C99 6.5.2] /// primary-expression /// postfix-expression '[' expression ']' /// postfix-expression '[' braced-init-list ']' /// postfix-expression '(' argument-expression-list[opt] ')' /// postfix-expression '.' identifier /// postfix-expression '->' identifier /// postfix-expression '++' /// postfix-expression '--' /// '(' type-name ')' '{' initializer-list '}' /// '(' type-name ')' '{' initializer-list ',' '}' /// /// argument-expression-list: [C99 6.5.2] /// argument-expression ...[opt] /// argument-expression-list ',' assignment-expression ...[opt] /// \endverbatim ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // Now that the primary-expression piece of the postfix-expression has been // parsed, see if there are any postfix-expression pieces here. SourceLocation Loc; while (1) { switch (Tok.getKind()) { case tok::code_completion: if (InMessageExpression) return LHS; Actions.CodeCompletePostfixExpression(getCurScope(), LHS); cutOffParsing(); return ExprError(); case tok::identifier: // If we see identifier: after an expression, and we're not already in a // message send, then this is probably a message send with a missing // opening bracket '['. if (getLangOpts().ObjC1 && !InMessageExpression && (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) { LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), nullptr, LHS.get()); break; } // Fall through; this isn't a message send. default: // Not a postfix-expression suffix. return LHS; case tok::l_square: { // postfix-expression: p-e '[' expression ']' // If we have a array postfix expression that starts on a new line and // Objective-C is enabled, it is highly likely that the user forgot a // semicolon after the base expression and that the array postfix-expr is // actually another message send. In this case, do some look-ahead to see // if the contents of the square brackets are obviously not a valid // expression and recover by pretending there is no suffix. if (getLangOpts().ObjC1 && Tok.isAtStartOfLine() && isSimpleObjCMessageExpression()) return LHS; // Reject array indices starting with a lambda-expression. '[[' is // reserved for attributes. if (CheckProhibitedCXX11Attribute()) { (void)Actions.CorrectDelayedTyposInExpr(LHS); return ExprError(); } BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); Loc = T.getOpenLocation(); ExprResult Idx, Length; SourceLocation ColonLoc; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Idx = ParseBraceInitializer(); } else if (getLangOpts().OpenMP) { ColonProtectionRAIIObject RAII(*this); // Parse [: or [ expr or [ expr : if (!Tok.is(tok::colon)) { // [ expr Idx = ParseExpression(); } if (Tok.is(tok::colon)) { // Consume ':' ColonLoc = ConsumeToken(); if (Tok.isNot(tok::r_square)) Length = ParseExpression(); } } else Idx = ParseExpression(); SourceLocation RLoc = Tok.getLocation(); ExprResult OrigLHS = LHS; if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() && Tok.is(tok::r_square)) { if (ColonLoc.isValid()) { LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(), ColonLoc, Length.get(), RLoc); } else { LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, Idx.get(), RLoc); } } else { LHS = ExprError(); } if (LHS.isInvalid()) { (void)Actions.CorrectDelayedTyposInExpr(OrigLHS); (void)Actions.CorrectDelayedTyposInExpr(Idx); (void)Actions.CorrectDelayedTyposInExpr(Length); LHS = ExprError(); Idx = ExprError(); } // Match the ']'. T.consumeClose(); break; } case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')' case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>' // '(' argument-expression-list[opt] ')' tok::TokenKind OpKind = Tok.getKind(); InMessageExpressionRAIIObject InMessage(*this, false); Expr *ExecConfig = nullptr; BalancedDelimiterTracker PT(*this, tok::l_paren); if (OpKind == tok::lesslessless) { ExprVector ExecConfigExprs; CommaLocsTy ExecConfigCommaLocs; SourceLocation OpenLoc = ConsumeToken(); if (ParseSimpleExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } SourceLocation CloseLoc; if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) { } else if (LHS.isInvalid()) { SkipUntil(tok::greatergreatergreater, StopAtSemi); } else { // There was an error closing the brackets Diag(Tok, diag::err_expected) << tok::greatergreatergreater; Diag(OpenLoc, diag::note_matching) << tok::lesslessless; SkipUntil(tok::greatergreatergreater, StopAtSemi); LHS = ExprError(); } if (!LHS.isInvalid()) { if (ExpectAndConsume(tok::l_paren)) LHS = ExprError(); else Loc = PrevTokLocation; } if (!LHS.isInvalid()) { ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(), OpenLoc, ExecConfigExprs, CloseLoc); if (ECResult.isInvalid()) LHS = ExprError(); else ExecConfig = ECResult.get(); } } else { PT.consumeOpen(); Loc = PT.getOpenLocation(); } ExprVector ArgExprs; CommaLocsTy CommaLocs; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCall(getCurScope(), LHS.get(), None); cutOffParsing(); return ExprError(); } if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { if (ParseExpressionList(ArgExprs, CommaLocs, [&] { Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs); })) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } else if (LHS.isInvalid()) { for (auto &E : ArgExprs) Actions.CorrectDelayedTyposInExpr(E); } } } // Match the ')'. if (LHS.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); } else if (Tok.isNot(tok::r_paren)) { bool HadDelayedTypo = false; if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get()) HadDelayedTypo = true; for (auto &E : ArgExprs) if (Actions.CorrectDelayedTyposInExpr(E).get() != E) HadDelayedTypo = true; // If there were delayed typos in the LHS or ArgExprs, call SkipUntil // instead of PT.consumeClose() to avoid emitting extra diagnostics for // the unmatched l_paren. if (HadDelayedTypo) SkipUntil(tok::r_paren, StopAtSemi); else PT.consumeClose(); LHS = ExprError(); } else { assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); LHS = Actions.ActOnCallExpr(getCurScope(), LHS.get(), Loc, ArgExprs, Tok.getLocation(), ExecConfig); PT.consumeClose(); } break; } case tok::arrow: case tok::period: { // postfix-expression: p-e '->' template[opt] id-expression // postfix-expression: p-e '.' template[opt] id-expression tok::TokenKind OpKind = Tok.getKind(); SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token. CXXScopeSpec SS; ParsedType ObjectType; bool MayBePseudoDestructor = false; if (getLangOpts().CPlusPlus && !LHS.isInvalid()) { Expr *Base = LHS.get(); const Type* BaseType = Base->getType().getTypePtrOrNull(); if (BaseType && Tok.is(tok::l_paren) && (BaseType->isFunctionType() || BaseType->isSpecificPlaceholderType(BuiltinType::BoundMember))) { Diag(OpLoc, diag::err_function_is_not_record) << OpKind << Base->getSourceRange() << FixItHint::CreateRemoval(OpLoc); return ParsePostfixExpressionSuffix(Base); } LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), Base, OpLoc, OpKind, ObjectType, MayBePseudoDestructor); if (LHS.isInvalid()) break; ParseOptionalCXXScopeSpecifier(SS, ObjectType, /*EnteringContext=*/false, &MayBePseudoDestructor); if (SS.isNotEmpty()) ObjectType = nullptr; } if (Tok.is(tok::code_completion)) { // Code completion for a member access expression. if (Expr *Base = LHS.get()) Actions.CodeCompleteMemberReferenceExpr( getCurScope(), Base, OpLoc, OpKind == tok::arrow, ExprStatementTokLoc == Base->getLocStart()); cutOffParsing(); return ExprError(); } if (MayBePseudoDestructor && !LHS.isInvalid()) { LHS = ParseCXXPseudoDestructor(LHS.get(), OpLoc, OpKind, SS, ObjectType); break; } // Either the action has told us that this cannot be a // pseudo-destructor expression (based on the type of base // expression), or we didn't see a '~' in the right place. We // can still parse a destructor name here, but in that case it // names a real destructor. // Allow explicit constructor calls in Microsoft mode. // FIXME: Add support for explicit call of template constructor. SourceLocation TemplateKWLoc; UnqualifiedId Name; if (getLangOpts().ObjC2 && OpKind == tok::period && Tok.is(tok::kw_class)) { // Objective-C++: // After a '.' in a member access expression, treat the keyword // 'class' as if it were an identifier. // // This hack allows property access to the 'class' method because it is // such a common method name. For other C++ keywords that are // Objective-C method names, one must use the message send syntax. IdentifierInfo *Id = Tok.getIdentifierInfo(); SourceLocation Loc = ConsumeToken(); Name.setIdentifier(Id, Loc); } else if (ParseUnqualifiedId(SS, /*EnteringContext=*/false, /*AllowDestructorName=*/true, /*AllowConstructorName=*/ getLangOpts().MicrosoftExt, ObjectType, TemplateKWLoc, Name)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } if (!LHS.isInvalid()) LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, OpKind, SS, TemplateKWLoc, Name, CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr); break; } case tok::plusplus: // postfix-expression: postfix-expression '++' case tok::minusminus: // postfix-expression: postfix-expression '--' if (!LHS.isInvalid()) { LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(), Tok.getKind(), LHS.get()); } ConsumeToken(); break; } } } /// ParseExprAfterUnaryExprOrTypeTrait - We parsed a typeof/sizeof/alignof/ /// vec_step and we are at the start of an expression or a parenthesized /// type-id. OpTok is the operand token (typeof/sizeof/alignof). Returns the /// expression (isCastExpr == false) or the type (isCastExpr == true). /// /// \verbatim /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C11] '_Alignof' '(' type-name ')' /// [C++0x] 'alignof' '(' type-id ')' /// /// [GNU] typeof-specifier: /// typeof ( expressions ) /// typeof ( type-name ) /// [GNU/C++] typeof unary-expression /// /// [OpenCL 1.1 6.11.12] vec_step built-in function: /// vec_step ( expressions ) /// vec_step ( type-name ) /// \endverbatim ExprResult Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, bool &isCastExpr, ParsedType &CastTy, SourceRange &CastRange) { assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step, tok::kw___builtin_omp_required_simd_align) && "Not a typeof/sizeof/alignof/vec_step expression!"); ExprResult Operand; // If the operand doesn't start with an '(', it must be an expression. if (Tok.isNot(tok::l_paren)) { // If construct allows a form without parenthesis, user may forget to put // pathenthesis around type name. if (OpTok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof)) { if (isTypeIdUnambiguously()) { DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); ParseDeclarator(DeclaratorInfo); SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation()); SourceLocation RParenLoc = PP.getLocForEndOfToken(PrevTokLocation); Diag(LParenLoc, diag::err_expected_parentheses_around_typename) << OpTok.getName() << FixItHint::CreateInsertion(LParenLoc, "(") << FixItHint::CreateInsertion(RParenLoc, ")"); isCastExpr = true; return ExprEmpty(); } } isCastExpr = false; if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo() << tok::l_paren; return ExprError(); } Operand = ParseCastExpression(true/*isUnaryExpression*/); } else { // If it starts with a '(', we know that it is either a parenthesized // type-name, or it is a unary-expression that starts with a compound // literal, or starts with a primary-expression that is a parenthesized // expression. ParenParseOption ExprType = CastExpr; SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/, false, CastTy, RParenLoc); CastRange = SourceRange(LParenLoc, RParenLoc); // If ParseParenExpression parsed a '(typename)' sequence only, then this is // a type. if (ExprType == CastExpr) { isCastExpr = true; return ExprEmpty(); } if (getLangOpts().CPlusPlus || OpTok.isNot(tok::kw_typeof)) { // GNU typeof in C requires the expression to be parenthesized. Not so for // sizeof/alignof or in C++. Therefore, the parenthesized expression is // the start of a unary-expression, but doesn't include any postfix // pieces. Parse these now if present. if (!Operand.isInvalid()) Operand = ParsePostfixExpressionSuffix(Operand.get()); } } // If we get here, the operand to the typeof/sizeof/alignof was an expresion. isCastExpr = false; return Operand; } /// \brief Parse a sizeof or alignof expression. /// /// \verbatim /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' /// [C++11] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C11] '_Alignof' '(' type-name ')' /// [C++11] 'alignof' '(' type-id ')' /// \endverbatim ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step, tok::kw___builtin_omp_required_simd_align) && "Not a sizeof/alignof/vec_step expression!"); Token OpTok = Tok; ConsumeToken(); // [C++11] 'sizeof' '...' '(' identifier ')' if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) { SourceLocation EllipsisLoc = ConsumeToken(); SourceLocation LParenLoc, RParenLoc; IdentifierInfo *Name = nullptr; SourceLocation NameLoc; if (Tok.is(tok::l_paren)) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); LParenLoc = T.getOpenLocation(); if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); T.consumeClose(); RParenLoc = T.getCloseLocation(); if (RParenLoc.isInvalid()) RParenLoc = PP.getLocForEndOfToken(NameLoc); } else { Diag(Tok, diag::err_expected_parameter_pack); SkipUntil(tok::r_paren, StopAtSemi); } } else if (Tok.is(tok::identifier)) { Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); LParenLoc = PP.getLocForEndOfToken(EllipsisLoc); RParenLoc = PP.getLocForEndOfToken(NameLoc); Diag(LParenLoc, diag::err_paren_sizeof_parameter_pack) << Name << FixItHint::CreateInsertion(LParenLoc, "(") << FixItHint::CreateInsertion(RParenLoc, ")"); } else { Diag(Tok, diag::err_sizeof_parameter_pack); } if (!Name) return ExprError(); EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, Sema::ReuseLambdaContextDecl); return Actions.ActOnSizeofParameterPackExpr(getCurScope(), OpTok.getLocation(), *Name, NameLoc, RParenLoc); } if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::warn_cxx98_compat_alignof); EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, Sema::ReuseLambdaContextDecl); bool isCastExpr; ParsedType CastTy; SourceRange CastRange; ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange); UnaryExprOrTypeTrait ExprKind = UETT_SizeOf; if (OpTok.isOneOf(tok::kw_alignof, tok::kw___alignof, tok::kw__Alignof)) ExprKind = UETT_AlignOf; else if (OpTok.is(tok::kw_vec_step)) ExprKind = UETT_VecStep; else if (OpTok.is(tok::kw___builtin_omp_required_simd_align)) ExprKind = UETT_OpenMPRequiredSimdAlign; if (isCastExpr) return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), ExprKind, /*isType=*/true, CastTy.getAsOpaquePtr(), CastRange); if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo(); // If we get here, the operand to the sizeof/alignof was an expresion. if (!Operand.isInvalid()) Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), ExprKind, /*isType=*/false, Operand.get(), CastRange); return Operand; } /// ParseBuiltinPrimaryExpression /// /// \verbatim /// primary-expression: [C99 6.5.1] /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')' /// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')' /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ',' /// assign-expr ')' /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')' /// [OCL] '__builtin_astype' '(' assignment-expression ',' type-name ')' /// /// [GNU] offsetof-member-designator: /// [GNU] identifier /// [GNU] offsetof-member-designator '.' identifier /// [GNU] offsetof-member-designator '[' expression ']' /// \endverbatim ExprResult Parser::ParseBuiltinPrimaryExpression() { ExprResult Res; const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo(); tok::TokenKind T = Tok.getKind(); SourceLocation StartLoc = ConsumeToken(); // Eat the builtin identifier. // All of these start with an open paren. if (Tok.isNot(tok::l_paren)) return ExprError(Diag(Tok, diag::err_expected_after) << BuiltinII << tok::l_paren); BalancedDelimiterTracker PT(*this, tok::l_paren); PT.consumeOpen(); // TODO: Build AST. switch (T) { default: llvm_unreachable("Not a builtin primary expression!"); case tok::kw___builtin_va_arg: { ExprResult Expr(ParseAssignmentExpression()); if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); Expr = ExprError(); } TypeResult Ty = ParseTypeName(); if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::err_expected) << tok::r_paren; Expr = ExprError(); } if (Expr.isInvalid() || Ty.isInvalid()) Res = ExprError(); else Res = Actions.ActOnVAArg(StartLoc, Expr.get(), Ty.get(), ConsumeParen()); break; } case tok::kw___builtin_offsetof: { SourceLocation TypeLoc = Tok.getLocation(); TypeResult Ty = ParseTypeName(); if (Ty.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } // We must have at least one identifier here. if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } // Keep track of the various subcomponents we see. SmallVector Comps; Comps.push_back(Sema::OffsetOfComponent()); Comps.back().isBrackets = false; Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken(); // FIXME: This loop leaks the index expressions on error. while (1) { if (Tok.is(tok::period)) { // offsetof-member-designator: offsetof-member-designator '.' identifier Comps.push_back(Sema::OffsetOfComponent()); Comps.back().isBrackets = false; Comps.back().LocStart = ConsumeToken(); if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected) << tok::identifier; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); Comps.back().LocEnd = ConsumeToken(); } else if (Tok.is(tok::l_square)) { if (CheckProhibitedCXX11Attribute()) return ExprError(); // offsetof-member-designator: offsetof-member-design '[' expression ']' Comps.push_back(Sema::OffsetOfComponent()); Comps.back().isBrackets = true; BalancedDelimiterTracker ST(*this, tok::l_square); ST.consumeOpen(); Comps.back().LocStart = ST.getOpenLocation(); Res = ParseExpression(); if (Res.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return Res; } Comps.back().U.E = Res.get(); ST.consumeClose(); Comps.back().LocEnd = ST.getCloseLocation(); } else { if (Tok.isNot(tok::r_paren)) { PT.consumeClose(); Res = ExprError(); } else if (Ty.isInvalid()) { Res = ExprError(); } else { PT.consumeClose(); Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc, Ty.get(), Comps, PT.getCloseLocation()); } break; } } break; } case tok::kw___builtin_choose_expr: { ExprResult Cond(ParseAssignmentExpression()); if (Cond.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return Cond; } if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } ExprResult Expr1(ParseAssignmentExpression()); if (Expr1.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return Expr1; } if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } ExprResult Expr2(ParseAssignmentExpression()); if (Expr2.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return Expr2; } if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::err_expected) << tok::r_paren; return ExprError(); } Res = Actions.ActOnChooseExpr(StartLoc, Cond.get(), Expr1.get(), Expr2.get(), ConsumeParen()); break; } case tok::kw___builtin_astype: { // The first argument is an expression to be converted, followed by a comma. ExprResult Expr(ParseAssignmentExpression()); if (Expr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } // Second argument is the type to bitcast to. TypeResult DestTy = ParseTypeName(); if (DestTy.isInvalid()) return ExprError(); // Attempt to consume the r-paren. if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::err_expected) << tok::r_paren; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } Res = Actions.ActOnAsTypeExpr(Expr.get(), DestTy.get(), StartLoc, ConsumeParen()); break; } case tok::kw___builtin_convertvector: { // The first argument is an expression to be converted, followed by a comma. ExprResult Expr(ParseAssignmentExpression()); if (Expr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } // Second argument is the type to bitcast to. TypeResult DestTy = ParseTypeName(); if (DestTy.isInvalid()) return ExprError(); // Attempt to consume the r-paren. if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::err_expected) << tok::r_paren; SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } Res = Actions.ActOnConvertVectorExpr(Expr.get(), DestTy.get(), StartLoc, ConsumeParen()); break; } } if (Res.isInvalid()) return ExprError(); // These can be followed by postfix-expr pieces because they are // primary-expressions. return ParsePostfixExpressionSuffix(Res.get()); } /// ParseParenExpression - This parses the unit that starts with a '(' token, /// based on what is allowed by ExprType. The actual thing parsed is returned /// in ExprType. If stopIfCastExpr is true, it will only return the parsed type, /// not the parsed cast-expression. /// /// \verbatim /// primary-expression: [C99 6.5.1] /// '(' expression ')' /// [GNU] '(' compound-statement ')' (if !ParenExprOnly) /// postfix-expression: [C99 6.5.2] /// '(' type-name ')' '{' initializer-list '}' /// '(' type-name ')' '{' initializer-list ',' '}' /// cast-expression: [C99 6.5.4] /// '(' type-name ')' cast-expression /// [ARC] bridged-cast-expression /// [ARC] bridged-cast-expression: /// (__bridge type-name) cast-expression /// (__bridge_transfer type-name) cast-expression /// (__bridge_retained type-name) cast-expression /// fold-expression: [C++1z] /// '(' cast-expression fold-operator '...' ')' /// '(' '...' fold-operator cast-expression ')' /// '(' cast-expression fold-operator '...' /// fold-operator cast-expression ')' /// \endverbatim ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, bool isTypeCast, ParsedType &CastTy, SourceLocation &RParenLoc) { assert(Tok.is(tok::l_paren) && "Not a paren expr!"); ColonProtectionRAIIObject ColonProtection(*this, false); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) return ExprError(); SourceLocation OpenLoc = T.getOpenLocation(); ExprResult Result(true); bool isAmbiguousTypeId; CastTy = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), ExprType >= CompoundLiteral? Sema::PCC_ParenthesizedExpression : Sema::PCC_Expression); cutOffParsing(); return ExprError(); } // Diagnose use of bridge casts in non-arc mode. bool BridgeCast = (getLangOpts().ObjC2 && Tok.isOneOf(tok::kw___bridge, tok::kw___bridge_transfer, tok::kw___bridge_retained, tok::kw___bridge_retain)); if (BridgeCast && !getLangOpts().ObjCAutoRefCount) { if (!TryConsumeToken(tok::kw___bridge)) { StringRef BridgeCastName = Tok.getName(); SourceLocation BridgeKeywordLoc = ConsumeToken(); if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc)) Diag(BridgeKeywordLoc, diag::warn_arc_bridge_cast_nonarc) << BridgeCastName << FixItHint::CreateReplacement(BridgeKeywordLoc, ""); } BridgeCast = false; } // None of these cases should fall through with an invalid Result // unless they've already reported an error. if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { Diag(Tok, diag::ext_gnu_statement_expr); if (!getCurScope()->getFnParent() && !getCurScope()->getBlockParent()) { Result = ExprError(Diag(OpenLoc, diag::err_stmtexpr_file_scope)); } else { // Find the nearest non-record decl context. Variables declared in a // statement expression behave as if they were declared in the enclosing // function, block, or other code construct. DeclContext *CodeDC = Actions.CurContext; while (CodeDC->isRecord() || isa(CodeDC)) { CodeDC = CodeDC->getParent(); assert(CodeDC && !CodeDC->isFileContext() && "statement expr not in code context"); } Sema::ContextRAII SavedContext(Actions, CodeDC, /*NewThisContext=*/false); Actions.ActOnStartStmtExpr(); StmtResult Stmt(ParseCompoundStatement(true)); ExprType = CompoundStmt; // If the substmt parsed correctly, build the AST node. if (!Stmt.isInvalid()) { Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.get(), Tok.getLocation()); } else { Actions.ActOnStmtExprError(); } } } else if (ExprType >= CompoundLiteral && BridgeCast) { tok::TokenKind tokenKind = Tok.getKind(); SourceLocation BridgeKeywordLoc = ConsumeToken(); // Parse an Objective-C ARC ownership cast expression. ObjCBridgeCastKind Kind; if (tokenKind == tok::kw___bridge) Kind = OBC_Bridge; else if (tokenKind == tok::kw___bridge_transfer) Kind = OBC_BridgeTransfer; else if (tokenKind == tok::kw___bridge_retained) Kind = OBC_BridgeRetained; else { // As a hopefully temporary workaround, allow __bridge_retain as // a synonym for __bridge_retained, but only in system headers. assert(tokenKind == tok::kw___bridge_retain); Kind = OBC_BridgeRetained; if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc)) Diag(BridgeKeywordLoc, diag::err_arc_bridge_retain) << FixItHint::CreateReplacement(BridgeKeywordLoc, "__bridge_retained"); } TypeResult Ty = ParseTypeName(); T.consumeClose(); ColonProtection.restore(); RParenLoc = T.getCloseLocation(); ExprResult SubExpr = ParseCastExpression(/*isUnaryExpression=*/false); if (Ty.isInvalid() || SubExpr.isInvalid()) return ExprError(); return Actions.ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind, BridgeKeywordLoc, Ty.get(), RParenLoc, SubExpr.get()); } else if (ExprType >= CompoundLiteral && isTypeIdInParens(isAmbiguousTypeId)) { // Otherwise, this is a compound literal expression or cast expression. // In C++, if the type-id is ambiguous we disambiguate based on context. // If stopIfCastExpr is true the context is a typeof/sizeof/alignof // in which case we should treat it as type-id. // if stopIfCastExpr is false, we need to determine the context past the // parens, so we defer to ParseCXXAmbiguousParenExpression for that. if (isAmbiguousTypeId && !stopIfCastExpr) { ExprResult res = ParseCXXAmbiguousParenExpression(ExprType, CastTy, T, ColonProtection); RParenLoc = T.getCloseLocation(); return res; } // Parse the type declarator. DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); ParseDeclarator(DeclaratorInfo); // If our type is followed by an identifier and either ':' or ']', then // this is probably an Objective-C message send where the leading '[' is // missing. Recover as if that were the case. if (!DeclaratorInfo.isInvalidType() && Tok.is(tok::identifier) && !InMessageExpression && getLangOpts().ObjC1 && (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) { TypeResult Ty; { InMessageExpressionRAIIObject InMessage(*this, false); Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } Result = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), Ty.get(), nullptr); } else { // Match the ')'. T.consumeClose(); ColonProtection.restore(); RParenLoc = T.getCloseLocation(); if (Tok.is(tok::l_brace)) { ExprType = CompoundLiteral; TypeResult Ty; { InMessageExpressionRAIIObject InMessage(*this, false); Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc); } if (ExprType == CastExpr) { // We parsed '(' type-name ')' and the thing after it wasn't a '{'. if (DeclaratorInfo.isInvalidType()) return ExprError(); // Note that this doesn't parse the subsequent cast-expression, it just // returns the parsed type to the callee. if (stopIfCastExpr) { TypeResult Ty; { InMessageExpressionRAIIObject InMessage(*this, false); Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } CastTy = Ty.get(); return ExprResult(); } // Reject the cast of super idiom in ObjC. if (Tok.is(tok::identifier) && getLangOpts().ObjC1 && Tok.getIdentifierInfo() == Ident_super && getCurScope()->isInObjcMethodScope() && GetLookAheadToken(1).isNot(tok::period)) { Diag(Tok.getLocation(), diag::err_illegal_super_cast) << SourceRange(OpenLoc, RParenLoc); return ExprError(); } // Parse the cast-expression that follows it next. // TODO: For cast expression with CastTy. Result = ParseCastExpression(/*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, /*isTypeCast=*/IsTypeCast); if (!Result.isInvalid()) { Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, DeclaratorInfo, CastTy, RParenLoc, Result.get()); } return Result; } Diag(Tok, diag::err_expected_lbrace_in_compound_literal); return ExprError(); } } else if (Tok.is(tok::ellipsis) && isFoldOperator(NextToken().getKind())) { return ParseFoldExpression(ExprResult(), T); } else if (isTypeCast) { // Parse the expression-list. InMessageExpressionRAIIObject InMessage(*this, false); ExprVector ArgExprs; CommaLocsTy CommaLocs; if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) { // FIXME: If we ever support comma expressions as operands to // fold-expressions, we'll need to allow multiple ArgExprs here. if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) - return ParseFoldExpression(Result, T); + return ParseFoldExpression(ArgExprs[0], T); ExprType = SimpleExpr; Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(), ArgExprs); } } else { InMessageExpressionRAIIObject InMessage(*this, false); Result = ParseExpression(MaybeTypeCast); if (!getLangOpts().CPlusPlus && MaybeTypeCast && Result.isUsable()) { // Correct typos in non-C++ code earlier so that implicit-cast-like // expressions are parsed correctly. Result = Actions.CorrectDelayedTyposInExpr(Result); } ExprType = SimpleExpr; if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) return ParseFoldExpression(Result, T); // Don't build a paren expression unless we actually match a ')'. if (!Result.isInvalid() && Tok.is(tok::r_paren)) Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.get()); } // Match the ')'. if (Result.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } T.consumeClose(); RParenLoc = T.getCloseLocation(); return Result; } /// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name /// and we are at the left brace. /// /// \verbatim /// postfix-expression: [C99 6.5.2] /// '(' type-name ')' '{' initializer-list '}' /// '(' type-name ')' '{' initializer-list ',' '}' /// \endverbatim ExprResult Parser::ParseCompoundLiteralExpression(ParsedType Ty, SourceLocation LParenLoc, SourceLocation RParenLoc) { assert(Tok.is(tok::l_brace) && "Not a compound literal!"); if (!getLangOpts().C99) // Compound literals don't exist in C90. Diag(LParenLoc, diag::ext_c99_compound_literal); ExprResult Result = ParseInitializer(); if (!Result.isInvalid() && Ty) return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.get()); return Result; } /// ParseStringLiteralExpression - This handles the various token types that /// form string literals, and also handles string concatenation [C99 5.1.1.2, /// translation phase #6]. /// /// \verbatim /// primary-expression: [C99 6.5.1] /// string-literal /// \verbatim ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) { assert(isTokenStringLiteral() && "Not a string literal!"); // String concat. Note that keywords like __func__ and __FUNCTION__ are not // considered to be strings for concatenation purposes. SmallVector StringToks; do { StringToks.push_back(Tok); ConsumeStringToken(); } while (isTokenStringLiteral()); // Pass the set of string tokens, ready for concatenation, to the actions. return Actions.ActOnStringLiteral(StringToks, AllowUserDefinedLiteral ? getCurScope() : nullptr); } /// ParseGenericSelectionExpression - Parse a C11 generic-selection /// [C11 6.5.1.1]. /// /// \verbatim /// generic-selection: /// _Generic ( assignment-expression , generic-assoc-list ) /// generic-assoc-list: /// generic-association /// generic-assoc-list , generic-association /// generic-association: /// type-name : assignment-expression /// default : assignment-expression /// \endverbatim ExprResult Parser::ParseGenericSelectionExpression() { assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected"); SourceLocation KeyLoc = ConsumeToken(); if (!getLangOpts().C11) Diag(KeyLoc, diag::ext_c11_generic_selection); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.expectAndConsume()) return ExprError(); ExprResult ControllingExpr; { // C11 6.5.1.1p3 "The controlling expression of a generic selection is // not evaluated." EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); ControllingExpr = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (ControllingExpr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } } if (ExpectAndConsume(tok::comma)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } SourceLocation DefaultLoc; TypeVector Types; ExprVector Exprs; do { ParsedType Ty; if (Tok.is(tok::kw_default)) { // C11 6.5.1.1p2 "A generic selection shall have no more than one default // generic association." if (!DefaultLoc.isInvalid()) { Diag(Tok, diag::err_duplicate_default_assoc); Diag(DefaultLoc, diag::note_previous_default_assoc); SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } DefaultLoc = ConsumeToken(); Ty = nullptr; } else { ColonProtectionRAIIObject X(*this); TypeResult TR = ParseTypeName(); if (TR.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } Ty = TR.get(); } Types.push_back(Ty); if (ExpectAndConsume(tok::colon)) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } // FIXME: These expressions should be parsed in a potentially potentially // evaluated context. ExprResult ER( Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); if (ER.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } Exprs.push_back(ER.get()); } while (TryConsumeToken(tok::comma)); T.consumeClose(); if (T.getCloseLocation().isInvalid()) return ExprError(); return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, T.getCloseLocation(), ControllingExpr.get(), Types, Exprs); } /// \brief Parse A C++1z fold-expression after the opening paren and optional /// left-hand-side expression. /// /// \verbatim /// fold-expression: /// ( cast-expression fold-operator ... ) /// ( ... fold-operator cast-expression ) /// ( cast-expression fold-operator ... fold-operator cast-expression ) ExprResult Parser::ParseFoldExpression(ExprResult LHS, BalancedDelimiterTracker &T) { if (LHS.isInvalid()) { T.skipToEnd(); return true; } tok::TokenKind Kind = tok::unknown; SourceLocation FirstOpLoc; if (LHS.isUsable()) { Kind = Tok.getKind(); assert(isFoldOperator(Kind) && "missing fold-operator"); FirstOpLoc = ConsumeToken(); } assert(Tok.is(tok::ellipsis) && "not a fold-expression"); SourceLocation EllipsisLoc = ConsumeToken(); ExprResult RHS; if (Tok.isNot(tok::r_paren)) { if (!isFoldOperator(Tok.getKind())) return Diag(Tok.getLocation(), diag::err_expected_fold_operator); if (Kind != tok::unknown && Tok.getKind() != Kind) Diag(Tok.getLocation(), diag::err_fold_operator_mismatch) << SourceRange(FirstOpLoc); Kind = Tok.getKind(); ConsumeToken(); RHS = ParseExpression(); if (RHS.isInvalid()) { T.skipToEnd(); return true; } } Diag(EllipsisLoc, getLangOpts().CPlusPlus1z ? diag::warn_cxx14_compat_fold_expression : diag::ext_fold_expression); T.consumeClose(); return Actions.ActOnCXXFoldExpr(T.getOpenLocation(), LHS.get(), Kind, EllipsisLoc, RHS.get(), T.getCloseLocation()); } /// ParseExpressionList - Used for C/C++ (argument-)expression-list. /// /// \verbatim /// argument-expression-list: /// assignment-expression /// argument-expression-list , assignment-expression /// /// [C++] expression-list: /// [C++] assignment-expression /// [C++] expression-list , assignment-expression /// /// [C++0x] expression-list: /// [C++0x] initializer-list /// /// [C++0x] initializer-list /// [C++0x] initializer-clause ...[opt] /// [C++0x] initializer-list , initializer-clause ...[opt] /// /// [C++0x] initializer-clause: /// [C++0x] assignment-expression /// [C++0x] braced-init-list /// \endverbatim bool Parser::ParseExpressionList(SmallVectorImpl &Exprs, SmallVectorImpl &CommaLocs, std::function Completer) { bool SawError = false; while (1) { if (Tok.is(tok::code_completion)) { if (Completer) Completer(); else Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); cutOffParsing(); return true; } ExprResult Expr; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Expr = ParseBraceInitializer(); } else Expr = ParseAssignmentExpression(); if (Tok.is(tok::ellipsis)) Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken()); if (Expr.isInvalid()) { SkipUntil(tok::comma, tok::r_paren, StopBeforeMatch); SawError = true; } else { Exprs.push_back(Expr.get()); } if (Tok.isNot(tok::comma)) break; // Move to the next argument, remember where the comma was. CommaLocs.push_back(ConsumeToken()); } if (SawError) { // Ensure typos get diagnosed when errors were encountered while parsing the // expression list. for (auto &E : Exprs) { ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E); if (Expr.isUsable()) E = Expr.get(); } } return SawError; } /// ParseSimpleExpressionList - A simple comma-separated list of expressions, /// used for misc language extensions. /// /// \verbatim /// simple-expression-list: /// assignment-expression /// simple-expression-list , assignment-expression /// \endverbatim bool Parser::ParseSimpleExpressionList(SmallVectorImpl &Exprs, SmallVectorImpl &CommaLocs) { while (1) { ExprResult Expr = ParseAssignmentExpression(); if (Expr.isInvalid()) return true; Exprs.push_back(Expr.get()); if (Tok.isNot(tok::comma)) return false; // Move to the next argument, remember where the comma was. CommaLocs.push_back(ConsumeToken()); } } /// ParseBlockId - Parse a block-id, which roughly looks like int (int x). /// /// \verbatim /// [clang] block-id: /// [clang] specifier-qualifier-list block-declarator /// \endverbatim void Parser::ParseBlockId(SourceLocation CaretLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); return cutOffParsing(); } // Parse the specifier-qualifier-list piece. DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); // Parse the block-declarator. Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext); DeclaratorInfo.setFunctionDefinitionKind(FDK_Definition); ParseDeclarator(DeclaratorInfo); MaybeParseGNUAttributes(DeclaratorInfo); // Inform sema that we are starting a block. Actions.ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope()); } /// ParseBlockLiteralExpression - Parse a block literal, which roughly looks /// like ^(int x){ return x+1; } /// /// \verbatim /// block-literal: /// [clang] '^' block-args[opt] compound-statement /// [clang] '^' block-id compound-statement /// [clang] block-args: /// [clang] '(' parameter-list ')' /// \endverbatim ExprResult Parser::ParseBlockLiteralExpression() { assert(Tok.is(tok::caret) && "block literal starts with ^"); SourceLocation CaretLoc = ConsumeToken(); PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc, "block literal parsing"); // Enter a scope to hold everything within the block. This includes the // argument decls, decls within the compound expression, etc. This also // allows determining whether a variable reference inside the block is // within or outside of the block. ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope | Scope::DeclScope); // Inform sema that we are starting a block. Actions.ActOnBlockStart(CaretLoc, getCurScope()); // Parse the return type if present. DeclSpec DS(AttrFactory); Declarator ParamInfo(DS, Declarator::BlockLiteralContext); ParamInfo.setFunctionDefinitionKind(FDK_Definition); // FIXME: Since the return type isn't actually parsed, it can't be used to // fill ParamInfo with an initial valid range, so do it manually. ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation())); // If this block has arguments, parse them. There is no ambiguity here with // the expression case, because the expression case requires a parameter list. if (Tok.is(tok::l_paren)) { ParseParenDeclarator(ParamInfo); // Parse the pieces after the identifier as if we had "int(...)". // SetIdentifier sets the source range end, but in this case we're past // that location. SourceLocation Tmp = ParamInfo.getSourceRange().getEnd(); ParamInfo.SetIdentifier(nullptr, CaretLoc); ParamInfo.SetRangeEnd(Tmp); if (ParamInfo.isInvalidType()) { // If there was an error parsing the arguments, they may have // tried to use ^(x+y) which requires an argument list. Just // skip the whole block literal. Actions.ActOnBlockError(CaretLoc, getCurScope()); return ExprError(); } MaybeParseGNUAttributes(ParamInfo); // Inform sema that we are starting a block. Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope()); } else if (!Tok.is(tok::l_brace)) { ParseBlockId(CaretLoc); } else { // Otherwise, pretend we saw (void). ParsedAttributes attrs(AttrFactory); SourceLocation NoLoc; ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true, /*IsAmbiguous=*/false, /*RParenLoc=*/NoLoc, /*ArgInfo=*/nullptr, /*NumArgs=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, /*TypeQuals=*/0, /*RefQualifierIsLvalueRef=*/true, /*RefQualifierLoc=*/NoLoc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, /*DeclsInPrototype=*/None, CaretLoc, CaretLoc, ParamInfo), attrs, CaretLoc); MaybeParseGNUAttributes(ParamInfo); // Inform sema that we are starting a block. Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope()); } ExprResult Result(true); if (!Tok.is(tok::l_brace)) { // Saw something like: ^expr Diag(Tok, diag::err_expected_expression); Actions.ActOnBlockError(CaretLoc, getCurScope()); return ExprError(); } StmtResult Stmt(ParseCompoundStatementBody()); BlockScope.Exit(); if (!Stmt.isInvalid()) Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.get(), getCurScope()); else Actions.ActOnBlockError(CaretLoc, getCurScope()); return Result; } /// ParseObjCBoolLiteral - This handles the objective-c Boolean literals. /// /// '__objc_yes' /// '__objc_no' ExprResult Parser::ParseObjCBoolLiteral() { tok::TokenKind Kind = Tok.getKind(); return Actions.ActOnObjCBoolLiteral(ConsumeToken(), Kind); } /// Validate availability spec list, emitting diagnostics if necessary. Returns /// true if invalid. static bool CheckAvailabilitySpecList(Parser &P, ArrayRef AvailSpecs) { llvm::SmallSet Platforms; bool HasOtherPlatformSpec = false; bool Valid = true; for (const auto &Spec : AvailSpecs) { if (Spec.isOtherPlatformSpec()) { if (HasOtherPlatformSpec) { P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_star); Valid = false; } HasOtherPlatformSpec = true; continue; } bool Inserted = Platforms.insert(Spec.getPlatform()).second; if (!Inserted) { // Rule out multiple version specs referring to the same platform. // For example, we emit an error for: // @available(macos 10.10, macos 10.11, *) StringRef Platform = Spec.getPlatform(); P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_platform) << Spec.getEndLoc() << Platform; Valid = false; } } if (!HasOtherPlatformSpec) { SourceLocation InsertWildcardLoc = AvailSpecs.back().getEndLoc(); P.Diag(InsertWildcardLoc, diag::err_availability_query_wildcard_required) << FixItHint::CreateInsertion(InsertWildcardLoc, ", *"); return true; } return !Valid; } /// Parse availability query specification. /// /// availability-spec: /// '*' /// identifier version-tuple Optional Parser::ParseAvailabilitySpec() { if (Tok.is(tok::star)) { return AvailabilitySpec(ConsumeToken()); } else { // Parse the platform name. if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_avail_query_expected_platform_name); return None; } IdentifierLoc *PlatformIdentifier = ParseIdentifierLoc(); SourceRange VersionRange; VersionTuple Version = ParseVersionTuple(VersionRange); if (Version.empty()) return None; StringRef Platform = PlatformIdentifier->Ident->getName(); if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) { Diag(PlatformIdentifier->Loc, diag::err_avail_query_unrecognized_platform_name) << Platform; return None; } return AvailabilitySpec(Version, Platform, PlatformIdentifier->Loc, VersionRange.getEnd()); } } ExprResult Parser::ParseAvailabilityCheckExpr(SourceLocation BeginLoc) { assert(Tok.is(tok::kw___builtin_available) || Tok.isObjCAtKeyword(tok::objc_available)); // Eat the available or __builtin_available. ConsumeToken(); BalancedDelimiterTracker Parens(*this, tok::l_paren); if (Parens.expectAndConsume()) return ExprError(); SmallVector AvailSpecs; bool HasError = false; while (true) { Optional Spec = ParseAvailabilitySpec(); if (!Spec) HasError = true; else AvailSpecs.push_back(*Spec); if (!TryConsumeToken(tok::comma)) break; } if (HasError) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } CheckAvailabilitySpecList(*this, AvailSpecs); if (Parens.consumeClose()) return ExprError(); return Actions.ActOnObjCAvailabilityCheckExpr(AvailSpecs, BeginLoc, Parens.getCloseLocation()); } Index: vendor/clang/dist/lib/Sema/SemaLookup.cpp =================================================================== --- vendor/clang/dist/lib/Sema/SemaLookup.cpp (revision 313882) +++ vendor/clang/dist/lib/Sema/SemaLookup.cpp (revision 313883) @@ -1,5124 +1,5127 @@ //===--------------------- SemaLookup.cpp - Name Lookup ------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements name lookup for C, C++, Objective-C, and // Objective-C++. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclLookups.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleLoader.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/ADT/edit_distance.h" #include "llvm/Support/ErrorHandling.h" #include #include #include #include #include #include using namespace clang; using namespace sema; namespace { class UnqualUsingEntry { const DeclContext *Nominated; const DeclContext *CommonAncestor; public: UnqualUsingEntry(const DeclContext *Nominated, const DeclContext *CommonAncestor) : Nominated(Nominated), CommonAncestor(CommonAncestor) { } const DeclContext *getCommonAncestor() const { return CommonAncestor; } const DeclContext *getNominatedNamespace() const { return Nominated; } // Sort by the pointer value of the common ancestor. struct Comparator { bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) { return L.getCommonAncestor() < R.getCommonAncestor(); } bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) { return E.getCommonAncestor() < DC; } bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) { return DC < E.getCommonAncestor(); } }; }; /// A collection of using directives, as used by C++ unqualified /// lookup. class UnqualUsingDirectiveSet { typedef SmallVector ListTy; ListTy list; llvm::SmallPtrSet visited; public: UnqualUsingDirectiveSet() {} void visitScopeChain(Scope *S, Scope *InnermostFileScope) { // C++ [namespace.udir]p1: // During unqualified name lookup, the names appear as if they // were declared in the nearest enclosing namespace which contains // both the using-directive and the nominated namespace. DeclContext *InnermostFileDC = InnermostFileScope->getEntity(); assert(InnermostFileDC && InnermostFileDC->isFileContext()); for (; S; S = S->getParent()) { // C++ [namespace.udir]p1: // A using-directive shall not appear in class scope, but may // appear in namespace scope or in block scope. DeclContext *Ctx = S->getEntity(); if (Ctx && Ctx->isFileContext()) { visit(Ctx, Ctx); } else if (!Ctx || Ctx->isFunctionOrMethod()) { for (auto *I : S->using_directives()) visit(I, InnermostFileDC); } } } // Visits a context and collect all of its using directives // recursively. Treats all using directives as if they were // declared in the context. // // A given context is only every visited once, so it is important // that contexts be visited from the inside out in order to get // the effective DCs right. void visit(DeclContext *DC, DeclContext *EffectiveDC) { if (!visited.insert(DC).second) return; addUsingDirectives(DC, EffectiveDC); } // Visits a using directive and collects all of its using // directives recursively. Treats all using directives as if they // were declared in the effective DC. void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { DeclContext *NS = UD->getNominatedNamespace(); if (!visited.insert(NS).second) return; addUsingDirective(UD, EffectiveDC); addUsingDirectives(NS, EffectiveDC); } // Adds all the using directives in a context (and those nominated // by its using directives, transitively) as if they appeared in // the given effective context. void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) { SmallVector queue; while (true) { for (auto UD : DC->using_directives()) { DeclContext *NS = UD->getNominatedNamespace(); if (visited.insert(NS).second) { addUsingDirective(UD, EffectiveDC); queue.push_back(NS); } } if (queue.empty()) return; DC = queue.pop_back_val(); } } // Add a using directive as if it had been declared in the given // context. This helps implement C++ [namespace.udir]p3: // The using-directive is transitive: if a scope contains a // using-directive that nominates a second namespace that itself // contains using-directives, the effect is as if the // using-directives from the second namespace also appeared in // the first. void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { // Find the common ancestor between the effective context and // the nominated namespace. DeclContext *Common = UD->getNominatedNamespace(); while (!Common->Encloses(EffectiveDC)) Common = Common->getParent(); Common = Common->getPrimaryContext(); list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common)); } void done() { std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator()); } typedef ListTy::const_iterator const_iterator; const_iterator begin() const { return list.begin(); } const_iterator end() const { return list.end(); } llvm::iterator_range getNamespacesFor(DeclContext *DC) const { return llvm::make_range(std::equal_range(begin(), end(), DC->getPrimaryContext(), UnqualUsingEntry::Comparator())); } }; } // end anonymous namespace // Retrieve the set of identifier namespaces that correspond to a // specific kind of name lookup. static inline unsigned getIDNS(Sema::LookupNameKind NameKind, bool CPlusPlus, bool Redeclaration) { unsigned IDNS = 0; switch (NameKind) { case Sema::LookupObjCImplicitSelfParam: case Sema::LookupOrdinaryName: case Sema::LookupRedeclarationWithLinkage: case Sema::LookupLocalFriendName: IDNS = Decl::IDNS_Ordinary; if (CPlusPlus) { IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace; if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; } if (Redeclaration) IDNS |= Decl::IDNS_LocalExtern; break; case Sema::LookupOperatorName: // Operator lookup is its own crazy thing; it is not the same // as (e.g.) looking up an operator name for redeclaration. assert(!Redeclaration && "cannot do redeclaration operator lookup"); IDNS = Decl::IDNS_NonMemberOperator; break; case Sema::LookupTagName: if (CPlusPlus) { IDNS = Decl::IDNS_Type; // When looking for a redeclaration of a tag name, we add: // 1) TagFriend to find undeclared friend decls // 2) Namespace because they can't "overload" with tag decls. // 3) Tag because it includes class templates, which can't // "overload" with tag decls. if (Redeclaration) IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace; } else { IDNS = Decl::IDNS_Tag; } break; case Sema::LookupLabel: IDNS = Decl::IDNS_Label; break; case Sema::LookupMemberName: IDNS = Decl::IDNS_Member; if (CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary; break; case Sema::LookupNestedNameSpecifierName: IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace; break; case Sema::LookupNamespaceName: IDNS = Decl::IDNS_Namespace; break; case Sema::LookupUsingDeclName: assert(Redeclaration && "should only be used for redecl lookup"); IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Using | Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend | Decl::IDNS_LocalExtern; break; case Sema::LookupObjCProtocolName: IDNS = Decl::IDNS_ObjCProtocol; break; case Sema::LookupOMPReductionName: IDNS = Decl::IDNS_OMPReduction; break; case Sema::LookupAnyName: IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol | Decl::IDNS_Type; break; } return IDNS; } void LookupResult::configure() { IDNS = getIDNS(LookupKind, getSema().getLangOpts().CPlusPlus, isForRedeclaration()); // If we're looking for one of the allocation or deallocation // operators, make sure that the implicitly-declared new and delete // operators can be found. switch (NameInfo.getName().getCXXOverloadedOperator()) { case OO_New: case OO_Delete: case OO_Array_New: case OO_Array_Delete: getSema().DeclareGlobalNewDelete(); break; default: break; } // Compiler builtins are always visible, regardless of where they end // up being declared. if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) { if (unsigned BuiltinID = Id->getBuiltinID()) { if (!getSema().Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) AllowHidden = true; } } } bool LookupResult::sanity() const { // This function is never called by NDEBUG builds. assert(ResultKind != NotFound || Decls.size() == 0); assert(ResultKind != Found || Decls.size() == 1); assert(ResultKind != FoundOverloaded || Decls.size() > 1 || (Decls.size() == 1 && isa((*begin())->getUnderlyingDecl()))); assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved()); assert(ResultKind != Ambiguous || Decls.size() > 1 || (Decls.size() == 1 && (Ambiguity == AmbiguousBaseSubobjects || Ambiguity == AmbiguousBaseSubobjectTypes))); assert((Paths != nullptr) == (ResultKind == Ambiguous && (Ambiguity == AmbiguousBaseSubobjectTypes || Ambiguity == AmbiguousBaseSubobjects))); return true; } // Necessary because CXXBasePaths is not complete in Sema.h void LookupResult::deletePaths(CXXBasePaths *Paths) { delete Paths; } /// Get a representative context for a declaration such that two declarations /// will have the same context if they were found within the same scope. static DeclContext *getContextForScopeMatching(Decl *D) { // For function-local declarations, use that function as the context. This // doesn't account for scopes within the function; the caller must deal with // those. DeclContext *DC = D->getLexicalDeclContext(); if (DC->isFunctionOrMethod()) return DC; // Otherwise, look at the semantic context of the declaration. The // declaration must have been found there. return D->getDeclContext()->getRedeclContext(); } /// \brief Determine whether \p D is a better lookup result than \p Existing, /// given that they declare the same entity. static bool isPreferredLookupResult(Sema &S, Sema::LookupNameKind Kind, NamedDecl *D, NamedDecl *Existing) { // When looking up redeclarations of a using declaration, prefer a using // shadow declaration over any other declaration of the same entity. if (Kind == Sema::LookupUsingDeclName && isa(D) && !isa(Existing)) return true; auto *DUnderlying = D->getUnderlyingDecl(); auto *EUnderlying = Existing->getUnderlyingDecl(); // If they have different underlying declarations, prefer a typedef over the // original type (this happens when two type declarations denote the same // type), per a generous reading of C++ [dcl.typedef]p3 and p4. The typedef // might carry additional semantic information, such as an alignment override. // However, per C++ [dcl.typedef]p5, when looking up a tag name, prefer a tag // declaration over a typedef. if (DUnderlying->getCanonicalDecl() != EUnderlying->getCanonicalDecl()) { assert(isa(DUnderlying) && isa(EUnderlying)); bool HaveTag = isa(EUnderlying); bool WantTag = Kind == Sema::LookupTagName; return HaveTag != WantTag; } // Pick the function with more default arguments. // FIXME: In the presence of ambiguous default arguments, we should keep both, // so we can diagnose the ambiguity if the default argument is needed. // See C++ [over.match.best]p3. if (auto *DFD = dyn_cast(DUnderlying)) { auto *EFD = cast(EUnderlying); unsigned DMin = DFD->getMinRequiredArguments(); unsigned EMin = EFD->getMinRequiredArguments(); // If D has more default arguments, it is preferred. if (DMin != EMin) return DMin < EMin; // FIXME: When we track visibility for default function arguments, check // that we pick the declaration with more visible default arguments. } // Pick the template with more default template arguments. if (auto *DTD = dyn_cast(DUnderlying)) { auto *ETD = cast(EUnderlying); unsigned DMin = DTD->getTemplateParameters()->getMinRequiredArguments(); unsigned EMin = ETD->getTemplateParameters()->getMinRequiredArguments(); // If D has more default arguments, it is preferred. Note that default // arguments (and their visibility) is monotonically increasing across the // redeclaration chain, so this is a quick proxy for "is more recent". if (DMin != EMin) return DMin < EMin; // If D has more *visible* default arguments, it is preferred. Note, an // earlier default argument being visible does not imply that a later // default argument is visible, so we can't just check the first one. for (unsigned I = DMin, N = DTD->getTemplateParameters()->size(); I != N; ++I) { if (!S.hasVisibleDefaultArgument( ETD->getTemplateParameters()->getParam(I)) && S.hasVisibleDefaultArgument( DTD->getTemplateParameters()->getParam(I))) return true; } } // VarDecl can have incomplete array types, prefer the one with more complete // array type. if (VarDecl *DVD = dyn_cast(DUnderlying)) { VarDecl *EVD = cast(EUnderlying); if (EVD->getType()->isIncompleteType() && !DVD->getType()->isIncompleteType()) { // Prefer the decl with a more complete type if visible. return S.isVisible(DVD); } return false; // Avoid picking up a newer decl, just because it was newer. } // For most kinds of declaration, it doesn't really matter which one we pick. if (!isa(DUnderlying) && !isa(DUnderlying)) { // If the existing declaration is hidden, prefer the new one. Otherwise, // keep what we've got. return !S.isVisible(Existing); } // Pick the newer declaration; it might have a more precise type. for (Decl *Prev = DUnderlying->getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) if (Prev == EUnderlying) return true; return false; } /// Determine whether \p D can hide a tag declaration. static bool canHideTag(NamedDecl *D) { // C++ [basic.scope.declarative]p4: // Given a set of declarations in a single declarative region [...] // exactly one declaration shall declare a class name or enumeration name // that is not a typedef name and the other declarations shall all refer to // the same variable, non-static data member, or enumerator, or all refer // to functions and function templates; in this case the class name or // enumeration name is hidden. // C++ [basic.scope.hiding]p2: // A class name or enumeration name can be hidden by the name of a // variable, data member, function, or enumerator declared in the same // scope. // An UnresolvedUsingValueDecl always instantiates to one of these. D = D->getUnderlyingDecl(); return isa(D) || isa(D) || isa(D) || isa(D) || isa(D) || isa(D); } /// Resolves the result kind of this lookup. void LookupResult::resolveKind() { unsigned N = Decls.size(); // Fast case: no possible ambiguity. if (N == 0) { assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation); return; } // If there's a single decl, we need to examine it to decide what // kind of lookup this is. if (N == 1) { NamedDecl *D = (*Decls.begin())->getUnderlyingDecl(); if (isa(D)) ResultKind = FoundOverloaded; else if (isa(D)) ResultKind = FoundUnresolvedValue; return; } // Don't do any extra resolution if we've already resolved as ambiguous. if (ResultKind == Ambiguous) return; llvm::SmallDenseMap Unique; llvm::SmallDenseMap UniqueTypes; bool Ambiguous = false; bool HasTag = false, HasFunction = false; bool HasFunctionTemplate = false, HasUnresolved = false; NamedDecl *HasNonFunction = nullptr; llvm::SmallVector EquivalentNonFunctions; unsigned UniqueTagIndex = 0; unsigned I = 0; while (I < N) { NamedDecl *D = Decls[I]->getUnderlyingDecl(); D = cast(D->getCanonicalDecl()); // Ignore an invalid declaration unless it's the only one left. if (D->isInvalidDecl() && !(I == 0 && N == 1)) { Decls[I] = Decls[--N]; continue; } llvm::Optional ExistingI; // Redeclarations of types via typedef can occur both within a scope // and, through using declarations and directives, across scopes. There is // no ambiguity if they all refer to the same type, so unique based on the // canonical type. if (TypeDecl *TD = dyn_cast(D)) { QualType T = getSema().Context.getTypeDeclType(TD); auto UniqueResult = UniqueTypes.insert( std::make_pair(getSema().Context.getCanonicalType(T), I)); if (!UniqueResult.second) { // The type is not unique. ExistingI = UniqueResult.first->second; } } // For non-type declarations, check for a prior lookup result naming this // canonical declaration. if (!ExistingI) { auto UniqueResult = Unique.insert(std::make_pair(D, I)); if (!UniqueResult.second) { // We've seen this entity before. ExistingI = UniqueResult.first->second; } } if (ExistingI) { // This is not a unique lookup result. Pick one of the results and // discard the other. if (isPreferredLookupResult(getSema(), getLookupKind(), Decls[I], Decls[*ExistingI])) Decls[*ExistingI] = Decls[I]; Decls[I] = Decls[--N]; continue; } // Otherwise, do some decl type analysis and then continue. if (isa(D)) { HasUnresolved = true; } else if (isa(D)) { if (HasTag) Ambiguous = true; UniqueTagIndex = I; HasTag = true; } else if (isa(D)) { HasFunction = true; HasFunctionTemplate = true; } else if (isa(D)) { HasFunction = true; } else { if (HasNonFunction) { // If we're about to create an ambiguity between two declarations that // are equivalent, but one is an internal linkage declaration from one // module and the other is an internal linkage declaration from another // module, just skip it. if (getSema().isEquivalentInternalLinkageDeclaration(HasNonFunction, D)) { EquivalentNonFunctions.push_back(D); Decls[I] = Decls[--N]; continue; } Ambiguous = true; } HasNonFunction = D; } I++; } // C++ [basic.scope.hiding]p2: // A class name or enumeration name can be hidden by the name of // an object, function, or enumerator declared in the same // scope. If a class or enumeration name and an object, function, // or enumerator are declared in the same scope (in any order) // with the same name, the class or enumeration name is hidden // wherever the object, function, or enumerator name is visible. // But it's still an error if there are distinct tag types found, // even if they're not visible. (ref?) if (N > 1 && HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction || HasUnresolved)) { NamedDecl *OtherDecl = Decls[UniqueTagIndex ? 0 : N - 1]; if (isa(Decls[UniqueTagIndex]->getUnderlyingDecl()) && getContextForScopeMatching(Decls[UniqueTagIndex])->Equals( getContextForScopeMatching(OtherDecl)) && canHideTag(OtherDecl)) Decls[UniqueTagIndex] = Decls[--N]; else Ambiguous = true; } // FIXME: This diagnostic should really be delayed until we're done with // the lookup result, in case the ambiguity is resolved by the caller. if (!EquivalentNonFunctions.empty() && !Ambiguous) getSema().diagnoseEquivalentInternalLinkageDeclarations( getNameLoc(), HasNonFunction, EquivalentNonFunctions); Decls.set_size(N); if (HasNonFunction && (HasFunction || HasUnresolved)) Ambiguous = true; if (Ambiguous) setAmbiguous(LookupResult::AmbiguousReference); else if (HasUnresolved) ResultKind = LookupResult::FoundUnresolvedValue; else if (N > 1 || HasFunctionTemplate) ResultKind = LookupResult::FoundOverloaded; else ResultKind = LookupResult::Found; } void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { CXXBasePaths::const_paths_iterator I, E; for (I = P.begin(), E = P.end(); I != E; ++I) for (DeclContext::lookup_iterator DI = I->Decls.begin(), DE = I->Decls.end(); DI != DE; ++DI) addDecl(*DI); } void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) { Paths = new CXXBasePaths; Paths->swap(P); addDeclsFromBasePaths(*Paths); resolveKind(); setAmbiguous(AmbiguousBaseSubobjects); } void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) { Paths = new CXXBasePaths; Paths->swap(P); addDeclsFromBasePaths(*Paths); resolveKind(); setAmbiguous(AmbiguousBaseSubobjectTypes); } void LookupResult::print(raw_ostream &Out) { Out << Decls.size() << " result(s)"; if (isAmbiguous()) Out << ", ambiguous"; if (Paths) Out << ", base paths present"; for (iterator I = begin(), E = end(); I != E; ++I) { Out << "\n"; (*I)->print(Out, 2); } } LLVM_DUMP_METHOD void LookupResult::dump() { llvm::errs() << "lookup results for " << getLookupName().getAsString() << ":\n"; for (NamedDecl *D : *this) D->dump(); } /// \brief Lookup a builtin function, when name lookup would otherwise /// fail. static bool LookupBuiltin(Sema &S, LookupResult &R) { Sema::LookupNameKind NameKind = R.getLookupKind(); // If we didn't find a use of this identifier, and if the identifier // corresponds to a compiler builtin, create the decl object for the builtin // now, injecting it into translation unit scope, and return it. if (NameKind == Sema::LookupOrdinaryName || NameKind == Sema::LookupRedeclarationWithLinkage) { IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); if (II) { if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName) { if (II == S.getASTContext().getMakeIntegerSeqName()) { R.addDecl(S.getASTContext().getMakeIntegerSeqDecl()); return true; } else if (II == S.getASTContext().getTypePackElementName()) { R.addDecl(S.getASTContext().getTypePackElementDecl()); return true; } } // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined // library functions like 'malloc'. Instead, we'll just error. if ((S.getLangOpts().CPlusPlus || S.getLangOpts().OpenCL) && S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) return false; if (NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S.TUScope, R.isForRedeclaration(), R.getNameLoc())) { R.addDecl(D); return true; } } } } return false; } /// \brief Determine whether we can declare a special member function within /// the class at this point. static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) { // We need to have a definition for the class. if (!Class->getDefinition() || Class->isDependentContext()) return false; // We can't be in the middle of defining the class. return !Class->isBeingDefined(); } void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { if (!CanDeclareSpecialMemberFunction(Class)) return; // If the default constructor has not yet been declared, do so now. if (Class->needsImplicitDefaultConstructor()) DeclareImplicitDefaultConstructor(Class); // If the copy constructor has not yet been declared, do so now. if (Class->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(Class); // If the copy assignment operator has not yet been declared, do so now. if (Class->needsImplicitCopyAssignment()) DeclareImplicitCopyAssignment(Class); if (getLangOpts().CPlusPlus11) { // If the move constructor has not yet been declared, do so now. if (Class->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(Class); // If the move assignment operator has not yet been declared, do so now. if (Class->needsImplicitMoveAssignment()) DeclareImplicitMoveAssignment(Class); } // If the destructor has not yet been declared, do so now. if (Class->needsImplicitDestructor()) DeclareImplicitDestructor(Class); } /// \brief Determine whether this is the name of an implicitly-declared /// special member function. static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) { switch (Name.getNameKind()) { case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: return true; case DeclarationName::CXXOperatorName: return Name.getCXXOverloadedOperator() == OO_Equal; default: break; } return false; } /// \brief If there are any implicit member functions with the given name /// that need to be declared in the given declaration context, do so. static void DeclareImplicitMemberFunctionsWithName(Sema &S, DeclarationName Name, const DeclContext *DC) { if (!DC) return; switch (Name.getNameKind()) { case DeclarationName::CXXConstructorName: if (const CXXRecordDecl *Record = dyn_cast(DC)) if (Record->getDefinition() && CanDeclareSpecialMemberFunction(Record)) { CXXRecordDecl *Class = const_cast(Record); if (Record->needsImplicitDefaultConstructor()) S.DeclareImplicitDefaultConstructor(Class); if (Record->needsImplicitCopyConstructor()) S.DeclareImplicitCopyConstructor(Class); if (S.getLangOpts().CPlusPlus11 && Record->needsImplicitMoveConstructor()) S.DeclareImplicitMoveConstructor(Class); } break; case DeclarationName::CXXDestructorName: if (const CXXRecordDecl *Record = dyn_cast(DC)) if (Record->getDefinition() && Record->needsImplicitDestructor() && CanDeclareSpecialMemberFunction(Record)) S.DeclareImplicitDestructor(const_cast(Record)); break; case DeclarationName::CXXOperatorName: if (Name.getCXXOverloadedOperator() != OO_Equal) break; if (const CXXRecordDecl *Record = dyn_cast(DC)) { if (Record->getDefinition() && CanDeclareSpecialMemberFunction(Record)) { CXXRecordDecl *Class = const_cast(Record); if (Record->needsImplicitCopyAssignment()) S.DeclareImplicitCopyAssignment(Class); if (S.getLangOpts().CPlusPlus11 && Record->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(Class); } } break; default: break; } } // Adds all qualifying matches for a name within a decl context to the // given lookup result. Returns true if any matches were found. static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { bool Found = false; // Lazily declare C++ special member functions. if (S.getLangOpts().CPlusPlus) DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC); // Perform lookup into this declaration context. DeclContext::lookup_result DR = DC->lookup(R.getLookupName()); for (DeclContext::lookup_iterator I = DR.begin(), E = DR.end(); I != E; ++I) { NamedDecl *D = *I; if ((D = R.getAcceptableDecl(D))) { R.addDecl(D); Found = true; } } if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R)) return true; if (R.getLookupName().getNameKind() != DeclarationName::CXXConversionFunctionName || R.getLookupName().getCXXNameType()->isDependentType() || !isa(DC)) return Found; // C++ [temp.mem]p6: // A specialization of a conversion function template is not found by // name lookup. Instead, any conversion function templates visible in the // context of the use are considered. [...] const CXXRecordDecl *Record = cast(DC); if (!Record->isCompleteDefinition()) return Found; for (CXXRecordDecl::conversion_iterator U = Record->conversion_begin(), UEnd = Record->conversion_end(); U != UEnd; ++U) { FunctionTemplateDecl *ConvTemplate = dyn_cast(*U); if (!ConvTemplate) continue; // When we're performing lookup for the purposes of redeclaration, just // add the conversion function template. When we deduce template // arguments for specializations, we'll end up unifying the return // type of the new declaration with the type of the function template. if (R.isForRedeclaration()) { R.addDecl(ConvTemplate); Found = true; continue; } // C++ [temp.mem]p6: // [...] For each such operator, if argument deduction succeeds // (14.9.2.3), the resulting specialization is used as if found by // name lookup. // // When referencing a conversion function for any purpose other than // a redeclaration (such that we'll be building an expression with the // result), perform template argument deduction and place the // specialization into the result set. We do this to avoid forcing all // callers to perform special deduction for conversion functions. TemplateDeductionInfo Info(R.getNameLoc()); FunctionDecl *Specialization = nullptr; const FunctionProtoType *ConvProto = ConvTemplate->getTemplatedDecl()->getType()->getAs(); assert(ConvProto && "Nonsensical conversion function template type"); // Compute the type of the function that we would expect the conversion // function to have, if it were to match the name given. // FIXME: Calling convention! FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_C); EPI.ExceptionSpec = EST_None; QualType ExpectedType = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), None, EPI); // Perform template argument deduction against the type that we would // expect the function to have. if (R.getSema().DeduceTemplateArguments(ConvTemplate, nullptr, ExpectedType, Specialization, Info) == Sema::TDK_Success) { R.addDecl(Specialization); Found = true; } } return Found; } // Performs C++ unqualified lookup into the given file context. static bool CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, DeclContext *NS, UnqualUsingDirectiveSet &UDirs) { assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!"); // Perform direct name lookup into the LookupCtx. bool Found = LookupDirect(S, R, NS); // Perform direct name lookup into the namespaces nominated by the // using directives whose common ancestor is this namespace. for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(NS)) if (LookupDirect(S, R, UUE.getNominatedNamespace())) Found = true; R.resolveKind(); return Found; } static bool isNamespaceOrTranslationUnitScope(Scope *S) { if (DeclContext *Ctx = S->getEntity()) return Ctx->isFileContext(); return false; } // Find the next outer declaration context from this scope. This // routine actually returns the semantic outer context, which may // differ from the lexical context (encoded directly in the Scope // stack) when we are parsing a member of a class template. In this // case, the second element of the pair will be true, to indicate that // name lookup should continue searching in this semantic context when // it leaves the current template parameter scope. static std::pair findOuterContext(Scope *S) { DeclContext *DC = S->getEntity(); DeclContext *Lexical = nullptr; for (Scope *OuterS = S->getParent(); OuterS; OuterS = OuterS->getParent()) { if (OuterS->getEntity()) { Lexical = OuterS->getEntity(); break; } } // C++ [temp.local]p8: // In the definition of a member of a class template that appears // outside of the namespace containing the class template // definition, the name of a template-parameter hides the name of // a member of this namespace. // // Example: // // namespace N { // class C { }; // // template class B { // void f(T); // }; // } // // template void N::B::f(C) { // C b; // C is the template parameter, not N::C // } // // In this example, the lexical context we return is the // TranslationUnit, while the semantic context is the namespace N. if (!Lexical || !DC || !S->getParent() || !S->getParent()->isTemplateParamScope()) return std::make_pair(Lexical, false); // Find the outermost template parameter scope. // For the example, this is the scope for the template parameters of // template. Scope *OutermostTemplateScope = S->getParent(); while (OutermostTemplateScope->getParent() && OutermostTemplateScope->getParent()->isTemplateParamScope()) OutermostTemplateScope = OutermostTemplateScope->getParent(); // Find the namespace context in which the original scope occurs. In // the example, this is namespace N. DeclContext *Semantic = DC; while (!Semantic->isFileContext()) Semantic = Semantic->getParent(); // Find the declaration context just outside of the template // parameter scope. This is the context in which the template is // being lexically declaration (a namespace context). In the // example, this is the global scope. if (Lexical->isFileContext() && !Lexical->Equals(Semantic) && Lexical->Encloses(Semantic)) return std::make_pair(Semantic, true); return std::make_pair(Lexical, false); } namespace { /// An RAII object to specify that we want to find block scope extern /// declarations. struct FindLocalExternScope { FindLocalExternScope(LookupResult &R) : R(R), OldFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_LocalExtern) { R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary); } void restore() { R.setFindLocalExtern(OldFindLocalExtern); } ~FindLocalExternScope() { restore(); } LookupResult &R; bool OldFindLocalExtern; }; } // end anonymous namespace bool Sema::CppLookupName(LookupResult &R, Scope *S) { assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup"); DeclarationName Name = R.getLookupName(); Sema::LookupNameKind NameKind = R.getLookupKind(); // If this is the name of an implicitly-declared special member function, // go through the scope stack to implicitly declare if (isImplicitlyDeclaredMemberFunctionName(Name)) { for (Scope *PreS = S; PreS; PreS = PreS->getParent()) if (DeclContext *DC = PreS->getEntity()) DeclareImplicitMemberFunctionsWithName(*this, Name, DC); } // Implicitly declare member functions with the name we're looking for, if in // fact we are in a scope where it matters. Scope *Initial = S; IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); // First we lookup local scope. // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir] // ...During unqualified name lookup (3.4.1), the names appear as if // they were declared in the nearest enclosing namespace which contains // both the using-directive and the nominated namespace. // [Note: in this context, "contains" means "contains directly or // indirectly". // // For example: // namespace A { int i; } // void foo() { // int i; // { // using namespace A; // ++i; // finds local 'i', A::i appears at global scope // } // } // UnqualUsingDirectiveSet UDirs; bool VisitedUsingDirectives = false; bool LeftStartingScope = false; DeclContext *OutsideOfTemplateParamDC = nullptr; // When performing a scope lookup, we want to find local extern decls. FindLocalExternScope FindLocals(R); for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { DeclContext *Ctx = S->getEntity(); bool SearchNamespaceScope = true; // Check whether the IdResolver has anything in this scope. for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { if (NameKind == LookupRedeclarationWithLinkage && !(*I)->isTemplateParameter()) { // If it's a template parameter, we still find it, so we can diagnose // the invalid redeclaration. // Determine whether this (or a previous) declaration is // out-of-scope. if (!LeftStartingScope && !Initial->isDeclScope(*I)) LeftStartingScope = true; // If we found something outside of our starting scope that // does not have linkage, skip it. if (LeftStartingScope && !((*I)->hasLinkage())) { R.setShadowed(); continue; } } else { // We found something in this scope, we should not look at the // namespace scope SearchNamespaceScope = false; } R.addDecl(ND); } } if (!SearchNamespaceScope) { R.resolveKind(); if (S->isClassScope()) if (CXXRecordDecl *Record = dyn_cast_or_null(Ctx)) R.setNamingClass(Record); return true; } if (NameKind == LookupLocalFriendName && !S->isClassScope()) { // C++11 [class.friend]p11: // If a friend declaration appears in a local class and the name // specified is an unqualified name, a prior declaration is // looked up without considering scopes that are outside the // innermost enclosing non-class scope. return false; } if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and // found nothing, so look into the contexts between the // lexical and semantic declaration contexts returned by // findOuterContext(). This implements the name lookup behavior // of C++ [temp.local]p8. Ctx = OutsideOfTemplateParamDC; OutsideOfTemplateParamDC = nullptr; } if (Ctx) { DeclContext *OuterCtx; bool SearchAfterTemplateScope; std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S); if (SearchAfterTemplateScope) OutsideOfTemplateParamDC = OuterCtx; for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { // We do not directly look into transparent contexts, since // those entities will be found in the nearest enclosing // non-transparent context. if (Ctx->isTransparentContext()) continue; // We do not look directly into function or method contexts, // since all of the local variables and parameters of the // function/method are present within the Scope. if (Ctx->isFunctionOrMethod()) { // If we have an Objective-C instance method, look for ivars // in the corresponding interface. if (ObjCMethodDecl *Method = dyn_cast(Ctx)) { if (Method->isInstanceMethod() && Name.getAsIdentifierInfo()) if (ObjCInterfaceDecl *Class = Method->getClassInterface()) { ObjCInterfaceDecl *ClassDeclared; if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable( Name.getAsIdentifierInfo(), ClassDeclared)) { if (NamedDecl *ND = R.getAcceptableDecl(Ivar)) { R.addDecl(ND); R.resolveKind(); return true; } } } } continue; } // If this is a file context, we need to perform unqualified name // lookup considering using directives. if (Ctx->isFileContext()) { // If we haven't handled using directives yet, do so now. if (!VisitedUsingDirectives) { // Add using directives from this context up to the top level. for (DeclContext *UCtx = Ctx; UCtx; UCtx = UCtx->getParent()) { if (UCtx->isTransparentContext()) continue; UDirs.visit(UCtx, UCtx); } // Find the innermost file scope, so we can add using directives // from local scopes. Scope *InnermostFileScope = S; while (InnermostFileScope && !isNamespaceOrTranslationUnitScope(InnermostFileScope)) InnermostFileScope = InnermostFileScope->getParent(); UDirs.visitScopeChain(Initial, InnermostFileScope); UDirs.done(); VisitedUsingDirectives = true; } if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) { R.resolveKind(); return true; } continue; } // Perform qualified name lookup into this context. // FIXME: In some cases, we know that every name that could be found by // this qualified name lookup will also be on the identifier chain. For // example, inside a class without any base classes, we never need to // perform qualified lookup because all of the members are on top of the // identifier chain. if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true)) return true; } } } // Stop if we ran out of scopes. // FIXME: This really, really shouldn't be happening. if (!S) return false; // If we are looking for members, no need to look into global/namespace scope. if (NameKind == LookupMemberName) return false; // Collect UsingDirectiveDecls in all scopes, and recursively all // nominated namespaces by those using-directives. // // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we // don't build it for each lookup! if (!VisitedUsingDirectives) { UDirs.visitScopeChain(Initial, S); UDirs.done(); } // If we're not performing redeclaration lookup, do not look for local // extern declarations outside of a function scope. if (!R.isForRedeclaration()) FindLocals.restore(); // Lookup namespace scope, and global scope. // Unqualified name lookup in C++ requires looking into scopes // that aren't strictly lexical, and therefore we walk through the // context as well as walking through the scopes. for (; S; S = S->getParent()) { // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { if (NamedDecl *ND = R.getAcceptableDecl(*I)) { // We found something. Look for anything else in our scope // with this same name and in an acceptable identifier // namespace, so that we can construct an overload set if we // need to. Found = true; R.addDecl(ND); } } if (Found && S->isTemplateParamScope()) { R.resolveKind(); return true; } DeclContext *Ctx = S->getEntity(); if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and // found nothing, so look into the contexts between the // lexical and semantic declaration contexts returned by // findOuterContext(). This implements the name lookup behavior // of C++ [temp.local]p8. Ctx = OutsideOfTemplateParamDC; OutsideOfTemplateParamDC = nullptr; } if (Ctx) { DeclContext *OuterCtx; bool SearchAfterTemplateScope; std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S); if (SearchAfterTemplateScope) OutsideOfTemplateParamDC = OuterCtx; for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { // We do not directly look into transparent contexts, since // those entities will be found in the nearest enclosing // non-transparent context. if (Ctx->isTransparentContext()) continue; // If we have a context, and it's not a context stashed in the // template parameter scope for an out-of-line definition, also // look into that context. if (!(Found && S->isTemplateParamScope())) { assert(Ctx->isFileContext() && "We should have been looking only at file context here already."); // Look into context considering using-directives. if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) Found = true; } if (Found) { R.resolveKind(); return true; } if (R.isForRedeclaration() && !Ctx->isTransparentContext()) return false; } } if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext()) return false; } return !R.empty(); } /// \brief Find the declaration that a class temploid member specialization was /// instantiated from, or the member itself if it is an explicit specialization. static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); } Module *Sema::getOwningModule(Decl *Entity) { // If it's imported, grab its owning module. Module *M = Entity->getImportedOwningModule(); if (M || !isa(Entity) || !cast(Entity)->isHidden()) return M; assert(!Entity->isFromASTFile() && "hidden entity from AST file has no owning module"); if (!getLangOpts().ModulesLocalVisibility) { // If we're not tracking visibility locally, the only way a declaration // can be hidden and local is if it's hidden because it's parent is (for // instance, maybe this is a lazily-declared special member of an imported // class). auto *Parent = cast(Entity->getDeclContext()); assert(Parent->isHidden() && "unexpectedly hidden decl"); return getOwningModule(Parent); } // It's local and hidden; grab or compute its owning module. M = Entity->getLocalOwningModule(); if (M) return M; if (auto *Containing = PP.getModuleContainingLocation(Entity->getLocation())) { M = Containing; } else if (Entity->isInvalidDecl() || Entity->getLocation().isInvalid()) { // Don't bother tracking visibility for invalid declarations with broken // locations. cast(Entity)->setHidden(false); } else { // We need to assign a module to an entity that exists outside of any // module, so that we can hide it from modules that we textually enter. // Invent a fake module for all such entities. if (!CachedFakeTopLevelModule) { CachedFakeTopLevelModule = PP.getHeaderSearchInfo().getModuleMap().findOrCreateModule( "", nullptr, false, false).first; auto &SrcMgr = PP.getSourceManager(); SourceLocation StartLoc = SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID()); auto &TopLevel = ModuleScopes.empty() ? VisibleModules : ModuleScopes[0].OuterVisibleModules; TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc); } M = CachedFakeTopLevelModule; } if (M) Entity->setLocalOwningModule(M); return M; } void Sema::makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc) { if (auto *M = PP.getModuleContainingLocation(Loc)) Context.mergeDefinitionIntoModule(ND, M); else // We're not building a module; just make the definition visible. ND->setHidden(false); // If ND is a template declaration, make the template parameters // visible too. They're not (necessarily) within a mergeable DeclContext. if (auto *TD = dyn_cast(ND)) for (auto *Param : *TD->getTemplateParameters()) makeMergedDefinitionVisible(Param, Loc); } /// \brief Find the module in which the given declaration was defined. static Module *getDefiningModule(Sema &S, Decl *Entity) { if (FunctionDecl *FD = dyn_cast(Entity)) { // If this function was instantiated from a template, the defining module is // the module containing the pattern. if (FunctionDecl *Pattern = FD->getTemplateInstantiationPattern()) Entity = Pattern; } else if (CXXRecordDecl *RD = dyn_cast(Entity)) { if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern()) Entity = Pattern; } else if (EnumDecl *ED = dyn_cast(Entity)) { if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo()) Entity = getInstantiatedFrom(ED, MSInfo); } else if (VarDecl *VD = dyn_cast(Entity)) { // FIXME: Map from variable template specializations back to the template. if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) Entity = getInstantiatedFrom(VD, MSInfo); } // Walk up to the containing context. That might also have been instantiated // from a template. DeclContext *Context = Entity->getDeclContext(); if (Context->isFileContext()) return S.getOwningModule(Entity); return getDefiningModule(S, cast(Context)); } llvm::DenseSet &Sema::getLookupModules() { unsigned N = ActiveTemplateInstantiations.size(); for (unsigned I = ActiveTemplateInstantiationLookupModules.size(); I != N; ++I) { Module *M = getDefiningModule(*this, ActiveTemplateInstantiations[I].Entity); if (M && !LookupModulesCache.insert(M).second) M = nullptr; ActiveTemplateInstantiationLookupModules.push_back(M); } return LookupModulesCache; } bool Sema::hasVisibleMergedDefinition(NamedDecl *Def) { for (Module *Merged : Context.getModulesWithMergedDefinition(Def)) if (isModuleVisible(Merged)) return true; return false; } template static bool hasVisibleDefaultArgument(Sema &S, const ParmDecl *D, llvm::SmallVectorImpl *Modules) { if (!D->hasDefaultArgument()) return false; while (D) { auto &DefaultArg = D->getDefaultArgStorage(); if (!DefaultArg.isInherited() && S.isVisible(D)) return true; if (!DefaultArg.isInherited() && Modules) { auto *NonConstD = const_cast(D); Modules->push_back(S.getOwningModule(NonConstD)); const auto &Merged = S.Context.getModulesWithMergedDefinition(NonConstD); Modules->insert(Modules->end(), Merged.begin(), Merged.end()); } // If there was a previous default argument, maybe its parameter is visible. D = DefaultArg.getInheritedFrom(); } return false; } bool Sema::hasVisibleDefaultArgument(const NamedDecl *D, llvm::SmallVectorImpl *Modules) { if (auto *P = dyn_cast(D)) return ::hasVisibleDefaultArgument(*this, P, Modules); if (auto *P = dyn_cast(D)) return ::hasVisibleDefaultArgument(*this, P, Modules); return ::hasVisibleDefaultArgument(*this, cast(D), Modules); } bool Sema::hasVisibleMemberSpecialization( const NamedDecl *D, llvm::SmallVectorImpl *Modules) { assert(isa(D->getDeclContext()) && "not a member specialization"); for (auto *Redecl : D->redecls()) { // If the specialization is declared at namespace scope, then it's a member // specialization declaration. If it's lexically inside the class // definition then it was instantiated. // // FIXME: This is a hack. There should be a better way to determine this. // FIXME: What about MS-style explicit specializations declared within a // class definition? if (Redecl->getLexicalDeclContext()->isFileContext()) { auto *NonConstR = const_cast(cast(Redecl)); if (isVisible(NonConstR)) return true; if (Modules) { Modules->push_back(getOwningModule(NonConstR)); const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR); Modules->insert(Modules->end(), Merged.begin(), Merged.end()); } } } return false; } /// \brief Determine whether a declaration is visible to name lookup. /// /// This routine determines whether the declaration D is visible in the current /// lookup context, taking into account the current template instantiation /// stack. During template instantiation, a declaration is visible if it is /// visible from a module containing any entity on the template instantiation /// path (by instantiating a template, you allow it to see the declarations that /// your module can see, including those later on in your module). bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { assert(D->isHidden() && "should not call this: not in slow case"); Module *DeclModule = nullptr; if (SemaRef.getLangOpts().ModulesLocalVisibility) { DeclModule = SemaRef.getOwningModule(D); if (!DeclModule) { // getOwningModule() may have decided the declaration should not be hidden. assert(!D->isHidden() && "hidden decl not from a module"); return true; } // If the owning module is visible, and the decl is not module private, // then the decl is visible too. (Module private is ignored within the same // top-level module.) if ((!D->isFromASTFile() || !D->isModulePrivate()) && (SemaRef.isModuleVisible(DeclModule) || SemaRef.hasVisibleMergedDefinition(D))) return true; } // If this declaration is not at namespace scope nor module-private, // then it is visible if its lexical parent has a visible definition. DeclContext *DC = D->getLexicalDeclContext(); if (!D->isModulePrivate() && DC && !DC->isFileContext() && !isa(DC) && !isa(DC)) { // For a parameter, check whether our current template declaration's // lexical context is visible, not whether there's some other visible // definition of it, because parameters aren't "within" the definition. // // In C++ we need to check for a visible definition due to ODR merging, // and in C we must not because each declaration of a function gets its own // set of declarations for tags in prototype scope. if ((D->isTemplateParameter() || isa(D) || (isa(DC) && !SemaRef.getLangOpts().CPlusPlus)) ? isVisible(SemaRef, cast(DC)) : SemaRef.hasVisibleDefinition(cast(DC))) { if (SemaRef.ActiveTemplateInstantiations.empty() && // FIXME: Do something better in this case. !SemaRef.getLangOpts().ModulesLocalVisibility) { // Cache the fact that this declaration is implicitly visible because // its parent has a visible definition. D->setHidden(false); } return true; } return false; } // Find the extra places where we need to look. llvm::DenseSet &LookupModules = SemaRef.getLookupModules(); if (LookupModules.empty()) return false; if (!DeclModule) { DeclModule = SemaRef.getOwningModule(D); assert(DeclModule && "hidden decl not from a module"); } // If our lookup set contains the decl's module, it's visible. if (LookupModules.count(DeclModule)) return true; // If the declaration isn't exported, it's not visible in any other module. if (D->isModulePrivate()) return false; // Check whether DeclModule is transitively exported to an import of // the lookup set. return std::any_of(LookupModules.begin(), LookupModules.end(), [&](Module *M) { return M->isModuleVisible(DeclModule); }); } bool Sema::isVisibleSlow(const NamedDecl *D) { return LookupResult::isVisible(*this, const_cast(D)); } bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) { for (auto *D : R) { if (isVisible(D)) return true; } return New->isExternallyVisible(); } /// \brief Retrieve the visible declaration corresponding to D, if any. /// /// This routine determines whether the declaration D is visible in the current /// module, with the current imports. If not, it checks whether any /// redeclaration of D is visible, and if so, returns that declaration. /// /// \returns D, or a visible previous declaration of D, whichever is more recent /// and visible. If no declaration of D is visible, returns null. static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); for (auto RD : D->redecls()) { // Don't bother with extra checks if we already know this one isn't visible. if (RD == D) continue; auto ND = cast(RD); // FIXME: This is wrong in the case where the previous declaration is not // visible in the same scope as D. This needs to be done much more // carefully. if (LookupResult::isVisible(SemaRef, ND)) return ND; } return nullptr; } bool Sema::hasVisibleDeclarationSlow(const NamedDecl *D, llvm::SmallVectorImpl *Modules) { assert(!isVisible(D) && "not in slow case"); for (auto *Redecl : D->redecls()) { auto *NonConstR = const_cast(cast(Redecl)); if (isVisible(NonConstR)) return true; if (Modules) { Modules->push_back(getOwningModule(NonConstR)); const auto &Merged = Context.getModulesWithMergedDefinition(NonConstR); Modules->insert(Modules->end(), Merged.begin(), Merged.end()); } } return false; } NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { if (auto *ND = dyn_cast(D)) { // Namespaces are a bit of a special case: we expect there to be a lot of // redeclarations of some namespaces, all declarations of a namespace are // essentially interchangeable, all declarations are found by name lookup // if any is, and namespaces are never looked up during template // instantiation. So we benefit from caching the check in this case, and // it is correct to do so. auto *Key = ND->getCanonicalDecl(); if (auto *Acceptable = getSema().VisibleNamespaceCache.lookup(Key)) return Acceptable; auto *Acceptable = isVisible(getSema(), Key) ? Key : findAcceptableDecl(getSema(), Key); if (Acceptable) getSema().VisibleNamespaceCache.insert(std::make_pair(Key, Acceptable)); return Acceptable; } return findAcceptableDecl(getSema(), D); } /// @brief Perform unqualified name lookup starting from a given /// scope. /// /// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is /// used to find names within the current scope. For example, 'x' in /// @code /// int x; /// int f() { /// return x; // unqualified name look finds 'x' in the global scope /// } /// @endcode /// /// Different lookup criteria can find different names. For example, a /// particular scope can have both a struct and a function of the same /// name, and each can be found by certain lookup criteria. For more /// information about lookup criteria, see the documentation for the /// class LookupCriteria. /// /// @param S The scope from which unqualified name lookup will /// begin. If the lookup criteria permits, name lookup may also search /// in the parent scopes. /// /// @param [in,out] R Specifies the lookup to perform (e.g., the name to /// look up and the lookup kind), and is updated with the results of lookup /// including zero or more declarations and possibly additional information /// used to diagnose ambiguities. /// /// @returns \c true if lookup succeeded and false otherwise. bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { DeclarationName Name = R.getLookupName(); if (!Name) return false; LookupNameKind NameKind = R.getLookupKind(); if (!getLangOpts().CPlusPlus) { // Unqualified name lookup in C/Objective-C is purely lexical, so // search in the declarations attached to the name. if (NameKind == Sema::LookupRedeclarationWithLinkage) { // Find the nearest non-transparent declaration scope. while (!(S->getFlags() & Scope::DeclScope) || (S->getEntity() && S->getEntity()->isTransparentContext())) S = S->getParent(); } // When performing a scope lookup, we want to find local extern decls. FindLocalExternScope FindLocals(R); // Scan up the scope chain looking for a decl that matches this // identifier that is in the appropriate namespace. This search // should not take long, as shadowing of names is uncommon, and // deep shadowing is extremely uncommon. bool LeftStartingScope = false; for (IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); I != IEnd; ++I) if (NamedDecl *D = R.getAcceptableDecl(*I)) { if (NameKind == LookupRedeclarationWithLinkage) { // Determine whether this (or a previous) declaration is // out-of-scope. if (!LeftStartingScope && !S->isDeclScope(*I)) LeftStartingScope = true; // If we found something outside of our starting scope that // does not have linkage, skip it. if (LeftStartingScope && !((*I)->hasLinkage())) { R.setShadowed(); continue; } } else if (NameKind == LookupObjCImplicitSelfParam && !isa(*I)) continue; R.addDecl(D); // Check whether there are any other declarations with the same name // and in the same scope. if (I != IEnd) { // Find the scope in which this declaration was declared (if it // actually exists in a Scope). while (S && !S->isDeclScope(D)) S = S->getParent(); // If the scope containing the declaration is the translation unit, // then we'll need to perform our checks based on the matching // DeclContexts rather than matching scopes. if (S && isNamespaceOrTranslationUnitScope(S)) S = nullptr; // Compute the DeclContext, if we need it. DeclContext *DC = nullptr; if (!S) DC = (*I)->getDeclContext()->getRedeclContext(); IdentifierResolver::iterator LastI = I; for (++LastI; LastI != IEnd; ++LastI) { if (S) { // Match based on scope. if (!S->isDeclScope(*LastI)) break; } else { // Match based on DeclContext. DeclContext *LastDC = (*LastI)->getDeclContext()->getRedeclContext(); if (!LastDC->Equals(DC)) break; } // If the declaration is in the right namespace and visible, add it. if (NamedDecl *LastD = R.getAcceptableDecl(*LastI)) R.addDecl(LastD); } R.resolveKind(); } return true; } } else { // Perform C++ unqualified name lookup. if (CppLookupName(R, S)) return true; } // If we didn't find a use of this identifier, and if the identifier // corresponds to a compiler builtin, create the decl object for the builtin // now, injecting it into translation unit scope, and return it. if (AllowBuiltinCreation && LookupBuiltin(*this, R)) return true; // If we didn't find a use of this identifier, the ExternalSource // may be able to handle the situation. // Note: some lookup failures are expected! // See e.g. R.isForRedeclaration(). return (ExternalSource && ExternalSource->LookupUnqualified(R, S)); } /// @brief Perform qualified name lookup in the namespaces nominated by /// using directives by the given context. /// /// C++98 [namespace.qual]p2: /// Given X::m (where X is a user-declared namespace), or given \::m /// (where X is the global namespace), let S be the set of all /// declarations of m in X and in the transitive closure of all /// namespaces nominated by using-directives in X and its used /// namespaces, except that using-directives are ignored in any /// namespace, including X, directly containing one or more /// declarations of m. No namespace is searched more than once in /// the lookup of a name. If S is the empty set, the program is /// ill-formed. Otherwise, if S has exactly one member, or if the /// context of the reference is a using-declaration /// (namespace.udecl), S is the required set of declarations of /// m. Otherwise if the use of m is not one that allows a unique /// declaration to be chosen from S, the program is ill-formed. /// /// C++98 [namespace.qual]p5: /// During the lookup of a qualified namespace member name, if the /// lookup finds more than one declaration of the member, and if one /// declaration introduces a class name or enumeration name and the /// other declarations either introduce the same object, the same /// enumerator or a set of functions, the non-type name hides the /// class or enumeration name if and only if the declarations are /// from the same namespace; otherwise (the declarations are from /// different namespaces), the program is ill-formed. static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, DeclContext *StartDC) { assert(StartDC->isFileContext() && "start context is not a file context"); DeclContext::udir_range UsingDirectives = StartDC->using_directives(); if (UsingDirectives.begin() == UsingDirectives.end()) return false; // We have at least added all these contexts to the queue. llvm::SmallPtrSet Visited; Visited.insert(StartDC); // We have not yet looked into these namespaces, much less added // their "using-children" to the queue. SmallVector Queue; // We have already looked into the initial namespace; seed the queue // with its using-children. for (auto *I : UsingDirectives) { NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace(); if (Visited.insert(ND).second) Queue.push_back(ND); } // The easiest way to implement the restriction in [namespace.qual]p5 // is to check whether any of the individual results found a tag // and, if so, to declare an ambiguity if the final result is not // a tag. bool FoundTag = false; bool FoundNonTag = false; LookupResult LocalR(LookupResult::Temporary, R); bool Found = false; while (!Queue.empty()) { NamespaceDecl *ND = Queue.pop_back_val(); // We go through some convolutions here to avoid copying results // between LookupResults. bool UseLocal = !R.empty(); LookupResult &DirectR = UseLocal ? LocalR : R; bool FoundDirect = LookupDirect(S, DirectR, ND); if (FoundDirect) { // First do any local hiding. DirectR.resolveKind(); // If the local result is a tag, remember that. if (DirectR.isSingleTagDecl()) FoundTag = true; else FoundNonTag = true; // Append the local results to the total results if necessary. if (UseLocal) { R.addAllDecls(LocalR); LocalR.clear(); } } // If we find names in this namespace, ignore its using directives. if (FoundDirect) { Found = true; continue; } for (auto I : ND->using_directives()) { NamespaceDecl *Nom = I->getNominatedNamespace(); if (Visited.insert(Nom).second) Queue.push_back(Nom); } } if (Found) { if (FoundTag && FoundNonTag) R.setAmbiguousQualifiedTagHiding(); else R.resolveKind(); } return Found; } /// \brief Callback that looks for any member of a class with the given name. static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name) { RecordDecl *BaseRecord = Specifier->getType()->getAs()->getDecl(); Path.Decls = BaseRecord->lookup(Name); return !Path.Decls.empty(); } /// \brief Determine whether the given set of member declarations contains only /// static members, nested types, and enumerators. template static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) { Decl *D = (*First)->getUnderlyingDecl(); if (isa(D) || isa(D) || isa(D)) return true; if (isa(D)) { // Determine whether all of the methods are static. bool AllMethodsAreStatic = true; for(; First != Last; ++First) { D = (*First)->getUnderlyingDecl(); if (!isa(D)) { assert(isa(D) && "Non-function must be a tag decl"); break; } if (!cast(D)->isStatic()) { AllMethodsAreStatic = false; break; } } if (AllMethodsAreStatic) return true; } return false; } /// \brief Perform qualified name lookup into a given context. /// /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find /// names when the context of those names is explicit specified, e.g., /// "std::vector" or "x->member", or as part of unqualified name lookup. /// /// Different lookup criteria can find different names. For example, a /// particular scope can have both a struct and a function of the same /// name, and each can be found by certain lookup criteria. For more /// information about lookup criteria, see the documentation for the /// class LookupCriteria. /// /// \param R captures both the lookup criteria and any lookup results found. /// /// \param LookupCtx The context in which qualified name lookup will /// search. If the lookup criteria permits, name lookup may also search /// in the parent contexts or (for C++ classes) base classes. /// /// \param InUnqualifiedLookup true if this is qualified name lookup that /// occurs as part of unqualified name lookup. /// /// \returns true if lookup succeeded, false if it failed. bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup) { assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); if (!R.getLookupName()) return false; // Make sure that the declaration context is complete. assert((!isa(LookupCtx) || LookupCtx->isDependentContext() || cast(LookupCtx)->isCompleteDefinition() || cast(LookupCtx)->isBeingDefined()) && "Declaration context must already be complete!"); struct QualifiedLookupInScope { bool oldVal; DeclContext *Context; // Set flag in DeclContext informing debugger that we're looking for qualified name QualifiedLookupInScope(DeclContext *ctx) : Context(ctx) { oldVal = ctx->setUseQualifiedLookup(); } ~QualifiedLookupInScope() { Context->setUseQualifiedLookup(oldVal); } } QL(LookupCtx); if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (isa(LookupCtx)) R.setNamingClass(cast(LookupCtx)); return true; } // Don't descend into implied contexts for redeclarations. // C++98 [namespace.qual]p6: // In a declaration for a namespace member in which the // declarator-id is a qualified-id, given that the qualified-id // for the namespace member has the form // nested-name-specifier unqualified-id // the unqualified-id shall name a member of the namespace // designated by the nested-name-specifier. // See also [class.mfct]p5 and [class.static.data]p2. if (R.isForRedeclaration()) return false; // If this is a namespace, look it up in the implied namespaces. if (LookupCtx->isFileContext()) return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx); // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. CXXRecordDecl *LookupRec = dyn_cast(LookupCtx); if (!LookupRec || !LookupRec->getDefinition()) return false; // If we're performing qualified name lookup into a dependent class, // then we are actually looking into a current instantiation. If we have any // dependent base classes, then we either have to delay lookup until // template instantiation time (at which point all bases will be available) // or we have to fail. if (!InUnqualifiedLookup && LookupRec->isDependentContext() && LookupRec->hasAnyDependentBases()) { R.setNotFoundInCurrentInstantiation(); return false; } // Perform lookup into our base classes. CXXBasePaths Paths; Paths.setOrigin(LookupRec); // Look for this member in our base classes bool (*BaseCallback)(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name) = nullptr; switch (R.getLookupKind()) { case LookupObjCImplicitSelfParam: case LookupOrdinaryName: case LookupMemberName: case LookupRedeclarationWithLinkage: case LookupLocalFriendName: BaseCallback = &CXXRecordDecl::FindOrdinaryMember; break; case LookupTagName: BaseCallback = &CXXRecordDecl::FindTagMember; break; case LookupAnyName: BaseCallback = &LookupAnyMember; break; case LookupOMPReductionName: BaseCallback = &CXXRecordDecl::FindOMPReductionMember; break; case LookupUsingDeclName: // This lookup is for redeclarations only. case LookupOperatorName: case LookupNamespaceName: case LookupObjCProtocolName: case LookupLabel: // These lookups will never find a member in a C++ class (or base class). return false; case LookupNestedNameSpecifierName: BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember; break; } DeclarationName Name = R.getLookupName(); if (!LookupRec->lookupInBases( [=](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { return BaseCallback(Specifier, Path, Name); }, Paths)) return false; R.setNamingClass(LookupRec); // C++ [class.member.lookup]p2: // [...] If the resulting set of declarations are not all from // sub-objects of the same type, or the set has a nonstatic member // and includes members from distinct sub-objects, there is an // ambiguity and the program is ill-formed. Otherwise that set is // the result of the lookup. QualType SubobjectType; int SubobjectNumber = 0; AccessSpecifier SubobjectAccess = AS_none; for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end(); Path != PathEnd; ++Path) { const CXXBasePathElement &PathElement = Path->back(); // Pick the best (i.e. most permissive i.e. numerically lowest) access // across all paths. SubobjectAccess = std::min(SubobjectAccess, Path->Access); // Determine whether we're looking at a distinct sub-object or not. if (SubobjectType.isNull()) { // This is the first subobject we've looked at. Record its type. SubobjectType = Context.getCanonicalType(PathElement.Base->getType()); SubobjectNumber = PathElement.SubobjectNumber; continue; } if (SubobjectType != Context.getCanonicalType(PathElement.Base->getType())) { // We found members of the given name in two subobjects of // different types. If the declaration sets aren't the same, this // lookup is ambiguous. if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) { CXXBasePaths::paths_iterator FirstPath = Paths.begin(); DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin(); DeclContext::lookup_iterator CurrentD = Path->Decls.begin(); while (FirstD != FirstPath->Decls.end() && CurrentD != Path->Decls.end()) { if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() != (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl()) break; ++FirstD; ++CurrentD; } if (FirstD == FirstPath->Decls.end() && CurrentD == Path->Decls.end()) continue; } R.setAmbiguousBaseSubobjectTypes(Paths); return true; } if (SubobjectNumber != PathElement.SubobjectNumber) { // We have a different subobject of the same type. // C++ [class.member.lookup]p5: // A static member, a nested type or an enumerator defined in // a base class T can unambiguously be found even if an object // has more than one base class subobject of type T. if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) continue; // We have found a nonstatic member name in multiple, distinct // subobjects. Name lookup is ambiguous. R.setAmbiguousBaseSubobjects(Paths); return true; } } // Lookup in a base class succeeded; return these results. for (auto *D : Paths.front().Decls) { AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess, D->getAccess()); R.addDecl(D, AS); } R.resolveKind(); return true; } /// \brief Performs qualified name lookup or special type of lookup for /// "__super::" scope specifier. /// /// This routine is a convenience overload meant to be called from contexts /// that need to perform a qualified name lookup with an optional C++ scope /// specifier that might require special kind of lookup. /// /// \param R captures both the lookup criteria and any lookup results found. /// /// \param LookupCtx The context in which qualified name lookup will /// search. /// /// \param SS An optional C++ scope-specifier. /// /// \returns true if lookup succeeded, false if it failed. bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, CXXScopeSpec &SS) { auto *NNS = SS.getScopeRep(); if (NNS && NNS->getKind() == NestedNameSpecifier::Super) return LookupInSuper(R, NNS->getAsRecordDecl()); else return LookupQualifiedName(R, LookupCtx); } /// @brief Performs name lookup for a name that was parsed in the /// source code, and may contain a C++ scope specifier. /// /// This routine is a convenience routine meant to be called from /// contexts that receive a name and an optional C++ scope specifier /// (e.g., "N::M::x"). It will then perform either qualified or /// unqualified name lookup (with LookupQualifiedName or LookupName, /// respectively) on the given name and return those results. It will /// perform a special type of lookup for "__super::" scope specifier. /// /// @param S The scope from which unqualified name lookup will /// begin. /// /// @param SS An optional C++ scope-specifier, e.g., "::N::M". /// /// @param EnteringContext Indicates whether we are going to enter the /// context of the scope-specifier SS (if present). /// /// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation, bool EnteringContext) { if (SS && SS->isInvalid()) { // When the scope specifier is invalid, don't even look for // anything. return false; } if (SS && SS->isSet()) { NestedNameSpecifier *NNS = SS->getScopeRep(); if (NNS->getKind() == NestedNameSpecifier::Super) return LookupInSuper(R, NNS->getAsRecordDecl()); if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) { // We have resolved the scope specifier to a particular declaration // contex, and will perform name lookup in that context. if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC)) return false; R.setContextRange(SS->getRange()); return LookupQualifiedName(R, DC); } // We could not resolve the scope specified to a specific declaration // context, which means that SS refers to an unknown specialization. // Name lookup can't find anything in this case. R.setNotFoundInCurrentInstantiation(); R.setContextRange(SS->getRange()); return false; } // Perform unqualified name lookup starting in the given scope. return LookupName(R, S, AllowBuiltinCreation); } /// \brief Perform qualified name lookup into all base classes of the given /// class. /// /// \param R captures both the lookup criteria and any lookup results found. /// /// \param Class The context in which qualified name lookup will /// search. Name lookup will search in all base classes merging the results. /// /// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) { // The access-control rules we use here are essentially the rules for // doing a lookup in Class that just magically skipped the direct // members of Class itself. That is, the naming class is Class, and the // access includes the access of the base. for (const auto &BaseSpec : Class->bases()) { CXXRecordDecl *RD = cast( BaseSpec.getType()->castAs()->getDecl()); LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind()); Result.setBaseObjectType(Context.getRecordType(Class)); LookupQualifiedName(Result, RD); // Copy the lookup results into the target, merging the base's access into // the path access. for (auto I = Result.begin(), E = Result.end(); I != E; ++I) { R.addDecl(I.getDecl(), CXXRecordDecl::MergeAccess(BaseSpec.getAccessSpecifier(), I.getAccess())); } Result.suppressDiagnostics(); } R.resolveKind(); R.setNamingClass(Class); return !R.empty(); } /// \brief Produce a diagnostic describing the ambiguity that resulted /// from name lookup. /// /// \param Result The result of the ambiguous lookup to be diagnosed. void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); DeclarationName Name = Result.getLookupName(); SourceLocation NameLoc = Result.getNameLoc(); SourceRange LookupRange = Result.getContextRange(); switch (Result.getAmbiguityKind()) { case LookupResult::AmbiguousBaseSubobjects: { CXXBasePaths *Paths = Result.getBasePaths(); QualType SubobjectType = Paths->front().back().Base->getType(); Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects) << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths) << LookupRange; DeclContext::lookup_iterator Found = Paths->front().Decls.begin(); while (isa(*Found) && cast(*Found)->isStatic()) ++Found; Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); break; } case LookupResult::AmbiguousBaseSubobjectTypes: { Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types) << Name << LookupRange; CXXBasePaths *Paths = Result.getBasePaths(); std::set DeclsPrinted; for (CXXBasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end(); Path != PathEnd; ++Path) { Decl *D = Path->Decls.front(); if (DeclsPrinted.insert(D).second) Diag(D->getLocation(), diag::note_ambiguous_member_found); } break; } case LookupResult::AmbiguousTagHiding: { Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange; llvm::SmallPtrSet TagDecls; for (auto *D : Result) if (TagDecl *TD = dyn_cast(D)) { TagDecls.insert(TD); Diag(TD->getLocation(), diag::note_hidden_tag); } for (auto *D : Result) if (!isa(D)) Diag(D->getLocation(), diag::note_hiding_object); // For recovery purposes, go ahead and implement the hiding. LookupResult::Filter F = Result.makeFilter(); while (F.hasNext()) { if (TagDecls.count(F.next())) F.erase(); } F.done(); break; } case LookupResult::AmbiguousReference: { Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange; for (auto *D : Result) Diag(D->getLocation(), diag::note_ambiguous_candidate) << D; break; } } } namespace { struct AssociatedLookup { AssociatedLookup(Sema &S, SourceLocation InstantiationLoc, Sema::AssociatedNamespaceSet &Namespaces, Sema::AssociatedClassSet &Classes) : S(S), Namespaces(Namespaces), Classes(Classes), InstantiationLoc(InstantiationLoc) { } Sema &S; Sema::AssociatedNamespaceSet &Namespaces; Sema::AssociatedClassSet &Classes; SourceLocation InstantiationLoc; }; } // end anonymous namespace static void addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T); static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces, DeclContext *Ctx) { // Add the associated namespace for this class. // We don't use DeclContext::getEnclosingNamespaceContext() as this may // be a locally scoped record. // We skip out of inline namespaces. The innermost non-inline namespace // contains all names of all its nested inline namespaces anyway, so we can // replace the entire inline namespace tree with its root. while (Ctx->isRecord() || Ctx->isTransparentContext() || Ctx->isInlineNamespace()) Ctx = Ctx->getParent(); if (Ctx->isFileContext()) Namespaces.insert(Ctx->getPrimaryContext()); } // \brief Add the associated classes and namespaces for argument-dependent // lookup that involves a template argument (C++ [basic.lookup.koenig]p2). static void addAssociatedClassesAndNamespaces(AssociatedLookup &Result, const TemplateArgument &Arg) { // C++ [basic.lookup.koenig]p2, last bullet: // -- [...] ; switch (Arg.getKind()) { case TemplateArgument::Null: break; case TemplateArgument::Type: // [...] the namespaces and classes associated with the types of the // template arguments provided for template type parameters (excluding // template template parameters) addAssociatedClassesAndNamespaces(Result, Arg.getAsType()); break; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: { // [...] the namespaces in which any template template arguments are // defined; and the classes in which any member templates used as // template template arguments are defined. TemplateName Template = Arg.getAsTemplateOrTemplatePattern(); if (ClassTemplateDecl *ClassTemplate = dyn_cast(Template.getAsTemplateDecl())) { DeclContext *Ctx = ClassTemplate->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) Result.Classes.insert(EnclosingClass); // Add the associated namespace for this class. CollectEnclosingNamespace(Result.Namespaces, Ctx); } break; } case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::Expression: case TemplateArgument::NullPtr: // [Note: non-type template arguments do not contribute to the set of // associated namespaces. ] break; case TemplateArgument::Pack: for (const auto &P : Arg.pack_elements()) addAssociatedClassesAndNamespaces(Result, P); break; } } // \brief Add the associated classes and namespaces for // argument-dependent lookup with an argument of class type // (C++ [basic.lookup.koenig]p2). static void addAssociatedClassesAndNamespaces(AssociatedLookup &Result, CXXRecordDecl *Class) { // Just silently ignore anything whose name is __va_list_tag. if (Class->getDeclName() == Result.S.VAListTagName) return; // C++ [basic.lookup.koenig]p2: // [...] // -- If T is a class type (including unions), its associated // classes are: the class itself; the class of which it is a // member, if any; and its direct and indirect base // classes. Its associated namespaces are the namespaces in // which its associated classes are defined. // Add the class of which it is a member, if any. DeclContext *Ctx = Class->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) Result.Classes.insert(EnclosingClass); // Add the associated namespace for this class. CollectEnclosingNamespace(Result.Namespaces, Ctx); // Add the class itself. If we've already seen this class, we don't // need to visit base classes. // // FIXME: That's not correct, we may have added this class only because it // was the enclosing class of another class, and in that case we won't have // added its base classes yet. if (!Result.Classes.insert(Class)) return; // -- If T is a template-id, its associated namespaces and classes are // the namespace in which the template is defined; for member // templates, the member template's class; the namespaces and classes // associated with the types of the template arguments provided for // template type parameters (excluding template template parameters); the // namespaces in which any template template arguments are defined; and // the classes in which any member templates used as template template // arguments are defined. [Note: non-type template arguments do not // contribute to the set of associated namespaces. ] if (ClassTemplateSpecializationDecl *Spec = dyn_cast(Class)) { DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) Result.Classes.insert(EnclosingClass); // Add the associated namespace for this class. CollectEnclosingNamespace(Result.Namespaces, Ctx); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]); } // Only recurse into base classes for complete types. if (!Result.S.isCompleteType(Result.InstantiationLoc, Result.S.Context.getRecordType(Class))) return; // Add direct and indirect base classes along with their associated // namespaces. SmallVector Bases; Bases.push_back(Class); while (!Bases.empty()) { // Pop this class off the stack. Class = Bases.pop_back_val(); // Visit the base classes. for (const auto &Base : Class->bases()) { const RecordType *BaseType = Base.getType()->getAs(); // In dependent contexts, we do ADL twice, and the first time around, // the base type might be a dependent TemplateSpecializationType, or a // TemplateTypeParmType. If that happens, simply ignore it. // FIXME: If we want to support export, we probably need to add the // namespace of the template in a TemplateSpecializationType, or even // the classes and namespaces of known non-dependent arguments. if (!BaseType) continue; CXXRecordDecl *BaseDecl = cast(BaseType->getDecl()); if (Result.Classes.insert(BaseDecl)) { // Find the associated namespace for this base class. DeclContext *BaseCtx = BaseDecl->getDeclContext(); CollectEnclosingNamespace(Result.Namespaces, BaseCtx); // Make sure we visit the bases of this base class. if (BaseDecl->bases_begin() != BaseDecl->bases_end()) Bases.push_back(BaseDecl); } } } } // \brief Add the associated classes and namespaces for // argument-dependent lookup with an argument of type T // (C++ [basic.lookup.koenig]p2). static void addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { // C++ [basic.lookup.koenig]p2: // // For each argument type T in the function call, there is a set // of zero or more associated namespaces and a set of zero or more // associated classes to be considered. The sets of namespaces and // classes is determined entirely by the types of the function // arguments (and the namespace of any template template // argument). Typedef names and using-declarations used to specify // the types do not contribute to this set. The sets of namespaces // and classes are determined in the following way: SmallVector Queue; const Type *T = Ty->getCanonicalTypeInternal().getTypePtr(); while (true) { switch (T->getTypeClass()) { #define TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: #define ABSTRACT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" // T is canonical. We can also ignore dependent types because // we don't need to do ADL at the definition point, but if we // wanted to implement template export (or if we find some other // use for associated classes and namespaces...) this would be // wrong. break; // -- If T is a pointer to U or an array of U, its associated // namespaces and classes are those associated with U. case Type::Pointer: T = cast(T)->getPointeeType().getTypePtr(); continue; case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: T = cast(T)->getElementType().getTypePtr(); continue; // -- If T is a fundamental type, its associated sets of // namespaces and classes are both empty. case Type::Builtin: break; // -- If T is a class type (including unions), its associated // classes are: the class itself; the class of which it is a // member, if any; and its direct and indirect base // classes. Its associated namespaces are the namespaces in // which its associated classes are defined. case Type::Record: { CXXRecordDecl *Class = cast(cast(T)->getDecl()); addAssociatedClassesAndNamespaces(Result, Class); break; } // -- If T is an enumeration type, its associated namespace is // the namespace in which it is defined. If it is class // member, its associated class is the member's class; else // it has no associated class. case Type::Enum: { EnumDecl *Enum = cast(T)->getDecl(); DeclContext *Ctx = Enum->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast(Ctx)) Result.Classes.insert(EnclosingClass); // Add the associated namespace for this class. CollectEnclosingNamespace(Result.Namespaces, Ctx); break; } // -- If T is a function type, its associated namespaces and // classes are those associated with the function parameter // types and those associated with the return type. case Type::FunctionProto: { const FunctionProtoType *Proto = cast(T); for (const auto &Arg : Proto->param_types()) Queue.push_back(Arg.getTypePtr()); // fallthrough } case Type::FunctionNoProto: { const FunctionType *FnType = cast(T); T = FnType->getReturnType().getTypePtr(); continue; } // -- If T is a pointer to a member function of a class X, its // associated namespaces and classes are those associated // with the function parameter types and return type, // together with those associated with X. // // -- If T is a pointer to a data member of class X, its // associated namespaces and classes are those associated // with the member type together with those associated with // X. case Type::MemberPointer: { const MemberPointerType *MemberPtr = cast(T); // Queue up the class type into which this points. Queue.push_back(MemberPtr->getClass()); // And directly continue with the pointee type. T = MemberPtr->getPointeeType().getTypePtr(); continue; } // As an extension, treat this like a normal pointer. case Type::BlockPointer: T = cast(T)->getPointeeType().getTypePtr(); continue; // References aren't covered by the standard, but that's such an // obvious defect that we cover them anyway. case Type::LValueReference: case Type::RValueReference: T = cast(T)->getPointeeType().getTypePtr(); continue; // These are fundamental types. case Type::Vector: case Type::ExtVector: case Type::Complex: break; // Non-deduced auto types only get here for error cases. case Type::Auto: break; // If T is an Objective-C object or interface type, or a pointer to an // object or interface type, the associated namespace is the global // namespace. case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl()); break; // Atomic types are just wrappers; use the associations of the // contained type. case Type::Atomic: T = cast(T)->getValueType().getTypePtr(); continue; case Type::Pipe: T = cast(T)->getElementType().getTypePtr(); continue; } if (Queue.empty()) break; T = Queue.pop_back_val(); } } /// \brief Find the associated classes and namespaces for /// argument-dependent lookup for a call with the given set of /// arguments. /// /// This routine computes the sets of associated classes and associated /// namespaces searched by argument-dependent lookup /// (C++ [basic.lookup.argdep]) for a given set of arguments. void Sema::FindAssociatedClassesAndNamespaces( SourceLocation InstantiationLoc, ArrayRef Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses) { AssociatedNamespaces.clear(); AssociatedClasses.clear(); AssociatedLookup Result(*this, InstantiationLoc, AssociatedNamespaces, AssociatedClasses); // C++ [basic.lookup.koenig]p2: // For each argument type T in the function call, there is a set // of zero or more associated namespaces and a set of zero or more // associated classes to be considered. The sets of namespaces and // classes is determined entirely by the types of the function // arguments (and the namespace of any template template // argument). for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { Expr *Arg = Args[ArgIdx]; if (Arg->getType() != Context.OverloadTy) { addAssociatedClassesAndNamespaces(Result, Arg->getType()); continue; } // [...] In addition, if the argument is the name or address of a // set of overloaded functions and/or function templates, its // associated classes and namespaces are the union of those // associated with each of the members of the set: the namespace // in which the function or function template is defined and the // classes and namespaces associated with its (non-dependent) // parameter types and return type. Arg = Arg->IgnoreParens(); if (UnaryOperator *unaryOp = dyn_cast(Arg)) if (unaryOp->getOpcode() == UO_AddrOf) Arg = unaryOp->getSubExpr(); UnresolvedLookupExpr *ULE = dyn_cast(Arg); if (!ULE) continue; for (const auto *D : ULE->decls()) { // Look through any using declarations to find the underlying function. const FunctionDecl *FDecl = D->getUnderlyingDecl()->getAsFunction(); // Add the classes and namespaces associated with the parameter // types and return type of this function. addAssociatedClassesAndNamespaces(Result, FDecl->getType()); } } } NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl) { LookupResult R(*this, Name, Loc, NameKind, Redecl); LookupName(R, S); return R.getAsSingle(); } /// \brief Find the protocol with the given name, if any. ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, RedeclarationKind Redecl) { Decl *D = LookupSingleName(TUScope, II, IdLoc, LookupObjCProtocolName, Redecl); return cast_or_null(D); } void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, UnresolvedSetImpl &Functions) { // C++ [over.match.oper]p3: // -- The set of non-member candidates is the result of the // unqualified lookup of operator@ in the context of the // expression according to the usual rules for name lookup in // unqualified function calls (3.4.2) except that all member // functions are ignored. DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName); LookupName(Operators, S); assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); Functions.append(Operators.begin(), Operators.end()); } Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMember SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis) { assert(CanDeclareSpecialMemberFunction(RD) && "doing special member lookup into record that isn't fully complete"); RD = RD->getDefinition(); if (RValueThis || ConstThis || VolatileThis) assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && "constructors and destructors always have unqualified lvalue this"); if (ConstArg || VolatileArg) assert((SM != CXXDefaultConstructor && SM != CXXDestructor) && "parameter-less special members can't have qualified arguments"); + // FIXME: Get the caller to pass in a location for the lookup. + SourceLocation LookupLoc = RD->getLocation(); + llvm::FoldingSetNodeID ID; ID.AddPointer(RD); ID.AddInteger(SM); ID.AddInteger(ConstArg); ID.AddInteger(VolatileArg); ID.AddInteger(RValueThis); ID.AddInteger(ConstThis); ID.AddInteger(VolatileThis); void *InsertPoint; SpecialMemberOverloadResult *Result = SpecialMemberCache.FindNodeOrInsertPos(ID, InsertPoint); // This was already cached if (Result) return Result; Result = BumpAlloc.Allocate(); Result = new (Result) SpecialMemberOverloadResult(ID); SpecialMemberCache.InsertNode(Result, InsertPoint); if (SM == CXXDestructor) { if (RD->needsImplicitDestructor()) DeclareImplicitDestructor(RD); CXXDestructorDecl *DD = RD->getDestructor(); assert(DD && "record without a destructor"); Result->setMethod(DD); Result->setKind(DD->isDeleted() ? SpecialMemberOverloadResult::NoMemberOrDeleted : SpecialMemberOverloadResult::Success); return Result; } // Prepare for overload resolution. Here we construct a synthetic argument // if necessary and make sure that implicit functions are declared. CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(RD)); DeclarationName Name; Expr *Arg = nullptr; unsigned NumArgs; QualType ArgType = CanTy; ExprValueKind VK = VK_LValue; if (SM == CXXDefaultConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); NumArgs = 0; if (RD->needsImplicitDefaultConstructor()) DeclareImplicitDefaultConstructor(RD); } else { if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); if (RD->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(RD); if (getLangOpts().CPlusPlus11 && RD->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(RD); } else { Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); if (RD->needsImplicitCopyAssignment()) DeclareImplicitCopyAssignment(RD); if (getLangOpts().CPlusPlus11 && RD->needsImplicitMoveAssignment()) DeclareImplicitMoveAssignment(RD); } if (ConstArg) ArgType.addConst(); if (VolatileArg) ArgType.addVolatile(); // This isn't /really/ specified by the standard, but it's implied // we should be working from an RValue in the case of move to ensure // that we prefer to bind to rvalue references, and an LValue in the // case of copy to ensure we don't bind to rvalue references. // Possibly an XValue is actually correct in the case of move, but // there is no semantic difference for class types in this restricted // case. if (SM == CXXCopyConstructor || SM == CXXCopyAssignment) VK = VK_LValue; else VK = VK_RValue; } - OpaqueValueExpr FakeArg(SourceLocation(), ArgType, VK); + OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK); if (SM != CXXDefaultConstructor) { NumArgs = 1; Arg = &FakeArg; } // Create the object argument QualType ThisTy = CanTy; if (ConstThis) ThisTy.addConst(); if (VolatileThis) ThisTy.addVolatile(); Expr::Classification Classification = - OpaqueValueExpr(SourceLocation(), ThisTy, + OpaqueValueExpr(LookupLoc, ThisTy, RValueThis ? VK_RValue : VK_LValue).Classify(Context); // Now we perform lookup on the name we computed earlier and do overload // resolution. Lookup is only performed directly into the class since there // will always be a (possibly implicit) declaration to shadow any others. - OverloadCandidateSet OCS(RD->getLocation(), OverloadCandidateSet::CSK_Normal); + OverloadCandidateSet OCS(LookupLoc, OverloadCandidateSet::CSK_Normal); DeclContext::lookup_result R = RD->lookup(Name); if (R.empty()) { // We might have no default constructor because we have a lambda's closure // type, rather than because there's some other declared constructor. // Every class has a copy/move constructor, copy/move assignment, and // destructor. assert(SM == CXXDefaultConstructor && "lookup for a constructor or assignment operator was empty"); Result->setMethod(nullptr); Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); return Result; } // Copy the candidates as our processing of them may load new declarations // from an external source and invalidate lookup_result. SmallVector Candidates(R.begin(), R.end()); for (NamedDecl *CandDecl : Candidates) { if (CandDecl->isInvalidDecl()) continue; DeclAccessPair Cand = DeclAccessPair::make(CandDecl, AS_public); auto CtorInfo = getConstructorInfo(Cand); if (CXXMethodDecl *M = dyn_cast(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) AddMethodCandidate(M, Cand, RD, ThisTy, Classification, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else if (CtorInfo) AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else AddOverloadCandidate(M, Cand, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); } else if (FunctionTemplateDecl *Tmpl = dyn_cast(Cand->getUnderlyingDecl())) { if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) AddMethodTemplateCandidate( Tmpl, Cand, RD, nullptr, ThisTy, Classification, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else if (CtorInfo) AddTemplateOverloadCandidate( CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); else AddTemplateOverloadCandidate( Tmpl, Cand, nullptr, llvm::makeArrayRef(&Arg, NumArgs), OCS, true); } else { assert(isa(Cand.getDecl()) && "illegal Kind of operator = Decl"); } } OverloadCandidateSet::iterator Best; - switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) { + switch (OCS.BestViableFunction(*this, LookupLoc, Best)) { case OR_Success: Result->setMethod(cast(Best->Function)); Result->setKind(SpecialMemberOverloadResult::Success); break; case OR_Deleted: Result->setMethod(cast(Best->Function)); Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); break; case OR_Ambiguous: Result->setMethod(nullptr); Result->setKind(SpecialMemberOverloadResult::Ambiguous); break; case OR_No_Viable_Function: Result->setMethod(nullptr); Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted); break; } return Result; } /// \brief Look up the default constructor for the given class. CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { SpecialMemberOverloadResult *Result = LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false, false, false); return cast_or_null(Result->getMethod()); } /// \brief Look up the copying constructor for the given class. CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, unsigned Quals) { assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy ctor arg"); SpecialMemberOverloadResult *Result = LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const, Quals & Qualifiers::Volatile, false, false, false); return cast_or_null(Result->getMethod()); } /// \brief Look up the moving constructor for the given class. CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class, unsigned Quals) { SpecialMemberOverloadResult *Result = LookupSpecialMember(Class, CXXMoveConstructor, Quals & Qualifiers::Const, Quals & Qualifiers::Volatile, false, false, false); return cast_or_null(Result->getMethod()); } /// \brief Look up the constructors for the given class. DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { // If the implicit constructors have not yet been declared, do so now. if (CanDeclareSpecialMemberFunction(Class)) { if (Class->needsImplicitDefaultConstructor()) DeclareImplicitDefaultConstructor(Class); if (Class->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(Class); if (getLangOpts().CPlusPlus11 && Class->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(Class); } CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class)); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T); return Class->lookup(Name); } /// \brief Look up the copying assignment operator for the given class. CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals, bool RValueThis, unsigned ThisQuals) { assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy assignment arg"); assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy assignment this"); SpecialMemberOverloadResult *Result = LookupSpecialMember(Class, CXXCopyAssignment, Quals & Qualifiers::Const, Quals & Qualifiers::Volatile, RValueThis, ThisQuals & Qualifiers::Const, ThisQuals & Qualifiers::Volatile); return Result->getMethod(); } /// \brief Look up the moving assignment operator for the given class. CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals, bool RValueThis, unsigned ThisQuals) { assert(!(ThisQuals & ~(Qualifiers::Const | Qualifiers::Volatile)) && "non-const, non-volatile qualifiers for copy assignment this"); SpecialMemberOverloadResult *Result = LookupSpecialMember(Class, CXXMoveAssignment, Quals & Qualifiers::Const, Quals & Qualifiers::Volatile, RValueThis, ThisQuals & Qualifiers::Const, ThisQuals & Qualifiers::Volatile); return Result->getMethod(); } /// \brief Look for the destructor of the given class. /// /// During semantic analysis, this routine should be used in lieu of /// CXXRecordDecl::getDestructor(). /// /// \returns The destructor for this class. CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { return cast(LookupSpecialMember(Class, CXXDestructor, false, false, false, false, false)->getMethod()); } /// LookupLiteralOperator - Determine which literal operator should be used for /// a user-defined literal, per C++11 [lex.ext]. /// /// Normal overload resolution is not used to select which literal operator to /// call for a user-defined literal. Look up the provided literal operator name, /// and filter the results to the appropriate set for the given argument types. Sema::LiteralOperatorLookupResult Sema::LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys, bool AllowRaw, bool AllowTemplate, bool AllowStringTemplate) { LookupName(R, S); assert(R.getResultKind() != LookupResult::Ambiguous && "literal operator lookup can't be ambiguous"); // Filter the lookup results appropriately. LookupResult::Filter F = R.makeFilter(); bool FoundRaw = false; bool FoundTemplate = false; bool FoundStringTemplate = false; bool FoundExactMatch = false; while (F.hasNext()) { Decl *D = F.next(); if (UsingShadowDecl *USD = dyn_cast(D)) D = USD->getTargetDecl(); // If the declaration we found is invalid, skip it. if (D->isInvalidDecl()) { F.erase(); continue; } bool IsRaw = false; bool IsTemplate = false; bool IsStringTemplate = false; bool IsExactMatch = false; if (FunctionDecl *FD = dyn_cast(D)) { if (FD->getNumParams() == 1 && FD->getParamDecl(0)->getType()->getAs()) IsRaw = true; else if (FD->getNumParams() == ArgTys.size()) { IsExactMatch = true; for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) { QualType ParamTy = FD->getParamDecl(ArgIdx)->getType(); if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) { IsExactMatch = false; break; } } } } if (FunctionTemplateDecl *FD = dyn_cast(D)) { TemplateParameterList *Params = FD->getTemplateParameters(); if (Params->size() == 1) IsTemplate = true; else IsStringTemplate = true; } if (IsExactMatch) { FoundExactMatch = true; AllowRaw = false; AllowTemplate = false; AllowStringTemplate = false; if (FoundRaw || FoundTemplate || FoundStringTemplate) { // Go through again and remove the raw and template decls we've // already found. F.restart(); FoundRaw = FoundTemplate = FoundStringTemplate = false; } } else if (AllowRaw && IsRaw) { FoundRaw = true; } else if (AllowTemplate && IsTemplate) { FoundTemplate = true; } else if (AllowStringTemplate && IsStringTemplate) { FoundStringTemplate = true; } else { F.erase(); } } F.done(); // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching // parameter type, that is used in preference to a raw literal operator // or literal operator template. if (FoundExactMatch) return LOLR_Cooked; // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal // operator template, but not both. if (FoundRaw && FoundTemplate) { Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) NoteOverloadCandidate(*I, (*I)->getUnderlyingDecl()->getAsFunction()); return LOLR_Error; } if (FoundRaw) return LOLR_Raw; if (FoundTemplate) return LOLR_Template; if (FoundStringTemplate) return LOLR_StringTemplate; // Didn't find anything we could use. Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw << (AllowTemplate || AllowStringTemplate); return LOLR_Error; } void ADLResult::insert(NamedDecl *New) { NamedDecl *&Old = Decls[cast(New->getCanonicalDecl())]; // If we haven't yet seen a decl for this key, or the last decl // was exactly this one, we're done. if (Old == nullptr || Old == New) { Old = New; return; } // Otherwise, decide which is a more recent redeclaration. FunctionDecl *OldFD = Old->getAsFunction(); FunctionDecl *NewFD = New->getAsFunction(); FunctionDecl *Cursor = NewFD; while (true) { Cursor = Cursor->getPreviousDecl(); // If we got to the end without finding OldFD, OldFD is the newer // declaration; leave things as they are. if (!Cursor) return; // If we do find OldFD, then NewFD is newer. if (Cursor == OldFD) break; // Otherwise, keep looking. } Old = New; } void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, ArrayRef Args, ADLResult &Result) { // Find all of the associated namespaces and classes based on the // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; AssociatedClassSet AssociatedClasses; FindAssociatedClassesAndNamespaces(Loc, Args, AssociatedNamespaces, AssociatedClasses); // C++ [basic.lookup.argdep]p3: // Let X be the lookup set produced by unqualified lookup (3.4.1) // and let Y be the lookup set produced by argument dependent // lookup (defined as follows). If X contains [...] then Y is // empty. Otherwise Y is the set of declarations found in the // namespaces associated with the argument types as described // below. The set of declarations found by the lookup of the name // is the union of X and Y. // // Here, we compute Y and add its members to the overloaded // candidate set. for (auto *NS : AssociatedNamespaces) { // When considering an associated namespace, the lookup is the // same as the lookup performed when the associated namespace is // used as a qualifier (3.4.3.2) except that: // // -- Any using-directives in the associated namespace are // ignored. // // -- Any namespace-scope friend functions declared in // associated classes are visible within their respective // namespaces even if they are not visible during an ordinary // lookup (11.4). DeclContext::lookup_result R = NS->lookup(Name); for (auto *D : R) { // If the only declaration here is an ordinary friend, consider // it only if it was declared in an associated classes. if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) { // If it's neither ordinarily visible nor a friend, we can't find it. if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0) continue; bool DeclaredInAssociatedClass = false; for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) { DeclContext *LexDC = DI->getLexicalDeclContext(); if (isa(LexDC) && AssociatedClasses.count(cast(LexDC)) && isVisible(cast(DI))) { DeclaredInAssociatedClass = true; break; } } if (!DeclaredInAssociatedClass) continue; } if (isa(D)) D = cast(D)->getTargetDecl(); if (!isa(D) && !isa(D)) continue; if (!isVisible(D) && !(D = findAcceptableDecl(*this, D))) continue; Result.insert(D); } } } //---------------------------------------------------------------------------- // Search for all visible declarations. //---------------------------------------------------------------------------- VisibleDeclConsumer::~VisibleDeclConsumer() { } bool VisibleDeclConsumer::includeHiddenDecls() const { return false; } namespace { class ShadowContextRAII; class VisibleDeclsRecord { public: /// \brief An entry in the shadow map, which is optimized to store a /// single declaration (the common case) but can also store a list /// of declarations. typedef llvm::TinyPtrVector ShadowMapEntry; private: /// \brief A mapping from declaration names to the declarations that have /// this name within a particular scope. typedef llvm::DenseMap ShadowMap; /// \brief A list of shadow maps, which is used to model name hiding. std::list ShadowMaps; /// \brief The declaration contexts we have already visited. llvm::SmallPtrSet VisitedContexts; friend class ShadowContextRAII; public: /// \brief Determine whether we have already visited this context /// (and, if not, note that we are going to visit that context now). bool visitedContext(DeclContext *Ctx) { return !VisitedContexts.insert(Ctx).second; } bool alreadyVisitedContext(DeclContext *Ctx) { return VisitedContexts.count(Ctx); } /// \brief Determine whether the given declaration is hidden in the /// current scope. /// /// \returns the declaration that hides the given declaration, or /// NULL if no such declaration exists. NamedDecl *checkHidden(NamedDecl *ND); /// \brief Add a declaration to the current shadow map. void add(NamedDecl *ND) { ShadowMaps.back()[ND->getDeclName()].push_back(ND); } }; /// \brief RAII object that records when we've entered a shadow context. class ShadowContextRAII { VisibleDeclsRecord &Visible; typedef VisibleDeclsRecord::ShadowMap ShadowMap; public: ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) { Visible.ShadowMaps.emplace_back(); } ~ShadowContextRAII() { Visible.ShadowMaps.pop_back(); } }; } // end anonymous namespace NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { unsigned IDNS = ND->getIdentifierNamespace(); std::list::reverse_iterator SM = ShadowMaps.rbegin(); for (std::list::reverse_iterator SMEnd = ShadowMaps.rend(); SM != SMEnd; ++SM) { ShadowMap::iterator Pos = SM->find(ND->getDeclName()); if (Pos == SM->end()) continue; for (auto *D : Pos->second) { // A tag declaration does not hide a non-tag declaration. if (D->hasTagIdentifierNamespace() && (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | Decl::IDNS_ObjCProtocol))) continue; // Protocols are in distinct namespaces from everything else. if (((D->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) || (IDNS & Decl::IDNS_ObjCProtocol)) && D->getIdentifierNamespace() != IDNS) continue; // Functions and function templates in the same scope overload // rather than hide. FIXME: Look for hiding based on function // signatures! if (D->getUnderlyingDecl()->isFunctionOrFunctionTemplate() && ND->getUnderlyingDecl()->isFunctionOrFunctionTemplate() && SM == ShadowMaps.rbegin()) continue; // We've found a declaration that hides this one. return D; } } return nullptr; } static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, bool QualifiedNameLookup, bool InBaseClass, VisibleDeclConsumer &Consumer, VisibleDeclsRecord &Visited) { if (!Ctx) return; // Make sure we don't visit the same context twice. if (Visited.visitedContext(Ctx->getPrimaryContext())) return; // Outside C++, lookup results for the TU live on identifiers. if (isa(Ctx) && !Result.getSema().getLangOpts().CPlusPlus) { auto &S = Result.getSema(); auto &Idents = S.Context.Idents; // Ensure all external identifiers are in the identifier table. if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) { std::unique_ptr Iter(External->getIdentifiers()); for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next()) Idents.get(Name); } // Walk all lookup results in the TU for each identifier. for (const auto &Ident : Idents) { for (auto I = S.IdResolver.begin(Ident.getValue()), E = S.IdResolver.end(); I != E; ++I) { if (S.IdResolver.isDeclInScope(*I, Ctx)) { if (NamedDecl *ND = Result.getAcceptableDecl(*I)) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); Visited.add(ND); } } } } return; } if (CXXRecordDecl *Class = dyn_cast(Ctx)) Result.getSema().ForceDeclarationOfImplicitMembers(Class); // Enumerate all of the results in this context. for (DeclContextLookupResult R : Ctx->lookups()) { for (auto *D : R) { if (auto *ND = Result.getAcceptableDecl(D)) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); Visited.add(ND); } } } // Traverse using directives for qualified name lookup. if (QualifiedNameLookup) { ShadowContextRAII Shadow(Visited); for (auto I : Ctx->using_directives()) { LookupVisibleDecls(I->getNominatedNamespace(), Result, QualifiedNameLookup, InBaseClass, Consumer, Visited); } } // Traverse the contexts of inherited C++ classes. if (CXXRecordDecl *Record = dyn_cast(Ctx)) { if (!Record->hasDefinition()) return; for (const auto &B : Record->bases()) { QualType BaseType = B.getType(); // Don't look into dependent bases, because name lookup can't look // there anyway. if (BaseType->isDependentType()) continue; const RecordType *Record = BaseType->getAs(); if (!Record) continue; // FIXME: It would be nice to be able to determine whether referencing // a particular member would be ambiguous. For example, given // // struct A { int member; }; // struct B { int member; }; // struct C : A, B { }; // // void f(C *c) { c->### } // // accessing 'member' would result in an ambiguity. However, we // could be smart enough to qualify the member with the base // class, e.g., // // c->B::member // // or // // c->A::member // Find results in this base class (and its bases). ShadowContextRAII Shadow(Visited); LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup, true, Consumer, Visited); } } // Traverse the contexts of Objective-C classes. if (ObjCInterfaceDecl *IFace = dyn_cast(Ctx)) { // Traverse categories. for (auto *Cat : IFace->visible_categories()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false, Consumer, Visited); } // Traverse protocols. for (auto *I : IFace->all_referenced_protocols()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer, Visited); } // Traverse the superclass. if (IFace->getSuperClass()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup, true, Consumer, Visited); } // If there is an implementation, traverse it. We do this to find // synthesized ivars. if (IFace->getImplementation()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(IFace->getImplementation(), Result, QualifiedNameLookup, InBaseClass, Consumer, Visited); } } else if (ObjCProtocolDecl *Protocol = dyn_cast(Ctx)) { for (auto *I : Protocol->protocols()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer, Visited); } } else if (ObjCCategoryDecl *Category = dyn_cast(Ctx)) { for (auto *I : Category->protocols()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer, Visited); } // If there is an implementation, traverse it. if (Category->getImplementation()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(Category->getImplementation(), Result, QualifiedNameLookup, true, Consumer, Visited); } } } static void LookupVisibleDecls(Scope *S, LookupResult &Result, UnqualUsingDirectiveSet &UDirs, VisibleDeclConsumer &Consumer, VisibleDeclsRecord &Visited) { if (!S) return; if (!S->getEntity() || (!S->getParent() && !Visited.alreadyVisitedContext(S->getEntity())) || (S->getEntity())->isFunctionOrMethod()) { FindLocalExternScope FindLocals(Result); // Walk through the declarations in this Scope. for (auto *D : S->decls()) { if (NamedDecl *ND = dyn_cast(D)) if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), nullptr, false); Visited.add(ND); } } } // FIXME: C++ [temp.local]p8 DeclContext *Entity = nullptr; if (S->getEntity()) { // Look into this scope's declaration context, along with any of its // parent lookup contexts (e.g., enclosing classes), up to the point // where we hit the context stored in the next outer scope. Entity = S->getEntity(); DeclContext *OuterCtx = findOuterContext(S).first; // FIXME for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { if (ObjCMethodDecl *Method = dyn_cast(Ctx)) { if (Method->isInstanceMethod()) { // For instance methods, look for ivars in the method's interface. LookupResult IvarResult(Result.getSema(), Result.getLookupName(), Result.getNameLoc(), Sema::LookupMemberName); if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) { LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, /*InBaseClass=*/false, Consumer, Visited); } } // We've already performed all of the name lookup that we need // to for Objective-C methods; the next context will be the // outer scope. break; } if (Ctx->isFunctionOrMethod()) continue; LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false, /*InBaseClass=*/false, Consumer, Visited); } } else if (!S->getParent()) { // Look into the translation unit scope. We walk through the translation // unit's declaration context, because the Scope itself won't have all of // the declarations if we loaded a precompiled header. // FIXME: We would like the translation unit's Scope object to point to the // translation unit, so we don't need this special "if" branch. However, // doing so would force the normal C++ name-lookup code to look into the // translation unit decl when the IdentifierInfo chains would suffice. // Once we fix that problem (which is part of a more general "don't look // in DeclContexts unless we have to" optimization), we can eliminate this. Entity = Result.getSema().Context.getTranslationUnitDecl(); LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false, /*InBaseClass=*/false, Consumer, Visited); } if (Entity) { // Lookup visible declarations in any namespaces found by using // directives. for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(Entity)) LookupVisibleDecls(const_cast(UUE.getNominatedNamespace()), Result, /*QualifiedNameLookup=*/false, /*InBaseClass=*/false, Consumer, Visited); } // Lookup names in the parent scope. ShadowContextRAII Shadow(Visited); LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited); } void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope) { // Determine the set of using directives available during // unqualified name lookup. Scope *Initial = S; UnqualUsingDirectiveSet UDirs; if (getLangOpts().CPlusPlus) { // Find the first namespace or translation-unit scope. while (S && !isNamespaceOrTranslationUnitScope(S)) S = S->getParent(); UDirs.visitScopeChain(Initial, S); } UDirs.done(); // Look for visible declarations. LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; if (!IncludeGlobalScope) Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited); } void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope) { LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; if (!IncludeGlobalScope) Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, /*InBaseClass=*/false, Consumer, Visited); } /// LookupOrCreateLabel - Do a name lookup of a label with the specified name. /// If GnuLabelLoc is a valid source location, then this is a definition /// of an __label__ label name, otherwise it is a normal label definition /// or use. LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, SourceLocation GnuLabelLoc) { // Do a lookup to see if we have a label with this name already. NamedDecl *Res = nullptr; if (GnuLabelLoc.isValid()) { // Local label definitions always shadow existing labels. Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc); Scope *S = CurScope; PushOnScopeChains(Res, S, true); return cast(Res); } // Not a GNU local label. Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration); // If we found a label, check to see if it is in the same context as us. // When in a Block, we don't want to reuse a label in an enclosing function. if (Res && Res->getDeclContext() != CurContext) Res = nullptr; if (!Res) { // If not forward referenced or defined already, create the backing decl. Res = LabelDecl::Create(Context, CurContext, Loc, II); Scope *S = CurScope->getFnParent(); assert(S && "Not in a function?"); PushOnScopeChains(Res, S, true); } return cast(Res); } //===----------------------------------------------------------------------===// // Typo correction //===----------------------------------------------------------------------===// static bool isCandidateViable(CorrectionCandidateCallback &CCC, TypoCorrection &Candidate) { Candidate.setCallbackDistance(CCC.RankCandidate(Candidate)); return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance; } static void LookupPotentialTypoResult(Sema &SemaRef, LookupResult &Res, IdentifierInfo *Name, Scope *S, CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, bool isObjCIvarLookup, bool FindHidden); /// \brief Check whether the declarations found for a typo correction are /// visible, and if none of them are, convert the correction to an 'import /// a module' correction. static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) { if (TC.begin() == TC.end()) return; TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end(); for (/**/; DI != DE; ++DI) if (!LookupResult::isVisible(SemaRef, *DI)) break; // Nothing to do if all decls are visible. if (DI == DE) return; llvm::SmallVector NewDecls(TC.begin(), DI); bool AnyVisibleDecls = !NewDecls.empty(); for (/**/; DI != DE; ++DI) { NamedDecl *VisibleDecl = *DI; if (!LookupResult::isVisible(SemaRef, *DI)) VisibleDecl = findAcceptableDecl(SemaRef, *DI); if (VisibleDecl) { if (!AnyVisibleDecls) { // Found a visible decl, discard all hidden ones. AnyVisibleDecls = true; NewDecls.clear(); } NewDecls.push_back(VisibleDecl); } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate()) NewDecls.push_back(*DI); } if (NewDecls.empty()) TC = TypoCorrection(); else { TC.setCorrectionDecls(NewDecls); TC.setRequiresImport(!AnyVisibleDecls); } } // Fill the supplied vector with the IdentifierInfo pointers for each piece of // the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::", // fill the vector with the IdentifierInfo pointers for "foo" and "bar"). static void getNestedNameSpecifierIdentifiers( NestedNameSpecifier *NNS, SmallVectorImpl &Identifiers) { if (NestedNameSpecifier *Prefix = NNS->getPrefix()) getNestedNameSpecifierIdentifiers(Prefix, Identifiers); else Identifiers.clear(); const IdentifierInfo *II = nullptr; switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: II = NNS->getAsIdentifier(); break; case NestedNameSpecifier::Namespace: if (NNS->getAsNamespace()->isAnonymousNamespace()) return; II = NNS->getAsNamespace()->getIdentifier(); break; case NestedNameSpecifier::NamespaceAlias: II = NNS->getAsNamespaceAlias()->getIdentifier(); break; case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier(); break; case NestedNameSpecifier::Global: case NestedNameSpecifier::Super: return; } if (II) Identifiers.push_back(II); } void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, bool InBaseClass) { // Don't consider hidden names for typo correction. if (Hiding) return; // Only consider entities with identifiers for names, ignoring // special names (constructors, overloaded operators, selectors, // etc.). IdentifierInfo *Name = ND->getIdentifier(); if (!Name) return; // Only consider visible declarations and declarations from modules with // names that exactly match. if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo && !findAcceptableDecl(SemaRef, ND)) return; FoundName(Name->getName()); } void TypoCorrectionConsumer::FoundName(StringRef Name) { // Compute the edit distance between the typo and the name of this // entity, and add the identifier to the list of results. addName(Name, nullptr); } void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) { // Compute the edit distance between the typo and this keyword, // and add the keyword to the list of results. addName(Keyword, nullptr, nullptr, true); } void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS, bool isKeyword) { // Use a simple length-based heuristic to determine the minimum possible // edit distance. If the minimum isn't good enough, bail out early. StringRef TypoStr = Typo->getName(); unsigned MinED = abs((int)Name.size() - (int)TypoStr.size()); if (MinED && TypoStr.size() / MinED < 3) return; // Compute an upper bound on the allowable edit distance, so that the // edit-distance algorithm can short-circuit. unsigned UpperBound = (TypoStr.size() + 2) / 3 + 1; unsigned ED = TypoStr.edit_distance(Name, true, UpperBound); if (ED >= UpperBound) return; TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED); if (isKeyword) TC.makeKeyword(); TC.setCorrectionRange(nullptr, Result.getLookupNameInfo()); addCorrection(TC); } static const unsigned MaxTypoDistanceResultSets = 5; void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) { StringRef TypoStr = Typo->getName(); StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName(); // For very short typos, ignore potential corrections that have a different // base identifier from the typo or which have a normalized edit distance // longer than the typo itself. if (TypoStr.size() < 3 && (Name != TypoStr || Correction.getEditDistance(true) > TypoStr.size())) return; // If the correction is resolved but is not viable, ignore it. if (Correction.isResolved()) { checkCorrectionVisibility(SemaRef, Correction); if (!Correction || !isCandidateViable(*CorrectionValidator, Correction)) return; } TypoResultList &CList = CorrectionResults[Correction.getEditDistance(false)][Name]; if (!CList.empty() && !CList.back().isResolved()) CList.pop_back(); if (NamedDecl *NewND = Correction.getCorrectionDecl()) { std::string CorrectionStr = Correction.getAsString(SemaRef.getLangOpts()); for (TypoResultList::iterator RI = CList.begin(), RIEnd = CList.end(); RI != RIEnd; ++RI) { // If the Correction refers to a decl already in the result list, // replace the existing result if the string representation of Correction // comes before the current result alphabetically, then stop as there is // nothing more to be done to add Correction to the candidate set. if (RI->getCorrectionDecl() == NewND) { if (CorrectionStr < RI->getAsString(SemaRef.getLangOpts())) *RI = Correction; return; } } } if (CList.empty() || Correction.isResolved()) CList.push_back(Correction); while (CorrectionResults.size() > MaxTypoDistanceResultSets) CorrectionResults.erase(std::prev(CorrectionResults.end())); } void TypoCorrectionConsumer::addNamespaces( const llvm::MapVector &KnownNamespaces) { SearchNamespaces = true; for (auto KNPair : KnownNamespaces) Namespaces.addNameSpecifier(KNPair.first); bool SSIsTemplate = false; if (NestedNameSpecifier *NNS = (SS && SS->isValid()) ? SS->getScopeRep() : nullptr) { if (const Type *T = NNS->getAsType()) SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization; } // Do not transform this into an iterator-based loop. The loop body can // trigger the creation of further types (through lazy deserialization) and // invalide iterators into this list. auto &Types = SemaRef.getASTContext().getTypes(); for (unsigned I = 0; I != Types.size(); ++I) { const auto *TI = Types[I]; if (CXXRecordDecl *CD = TI->getAsCXXRecordDecl()) { CD = CD->getCanonicalDecl(); if (!CD->isDependentType() && !CD->isAnonymousStructOrUnion() && !CD->isUnion() && CD->getIdentifier() && (SSIsTemplate || !isa(CD)) && (CD->isBeingDefined() || CD->isCompleteDefinition())) Namespaces.addNameSpecifier(CD); } } } const TypoCorrection &TypoCorrectionConsumer::getNextCorrection() { if (++CurrentTCIndex < ValidatedCorrections.size()) return ValidatedCorrections[CurrentTCIndex]; CurrentTCIndex = ValidatedCorrections.size(); while (!CorrectionResults.empty()) { auto DI = CorrectionResults.begin(); if (DI->second.empty()) { CorrectionResults.erase(DI); continue; } auto RI = DI->second.begin(); if (RI->second.empty()) { DI->second.erase(RI); performQualifiedLookups(); continue; } TypoCorrection TC = RI->second.pop_back_val(); if (TC.isResolved() || TC.requiresImport() || resolveCorrection(TC)) { ValidatedCorrections.push_back(TC); return ValidatedCorrections[CurrentTCIndex]; } } return ValidatedCorrections[0]; // The empty correction. } bool TypoCorrectionConsumer::resolveCorrection(TypoCorrection &Candidate) { IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo(); DeclContext *TempMemberContext = MemberContext; CXXScopeSpec *TempSS = SS.get(); retry_lookup: LookupPotentialTypoResult(SemaRef, Result, Name, S, TempSS, TempMemberContext, EnteringContext, CorrectionValidator->IsObjCIvarLookup, Name == Typo && !Candidate.WillReplaceSpecifier()); switch (Result.getResultKind()) { case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundUnresolvedValue: if (TempSS) { // Immediately retry the lookup without the given CXXScopeSpec TempSS = nullptr; Candidate.WillReplaceSpecifier(true); goto retry_lookup; } if (TempMemberContext) { if (SS && !TempSS) TempSS = SS.get(); TempMemberContext = nullptr; goto retry_lookup; } if (SearchNamespaces) QualifiedResults.push_back(Candidate); break; case LookupResult::Ambiguous: // We don't deal with ambiguities. break; case LookupResult::Found: case LookupResult::FoundOverloaded: // Store all of the Decls for overloaded symbols for (auto *TRD : Result) Candidate.addCorrectionDecl(TRD); checkCorrectionVisibility(SemaRef, Candidate); if (!isCandidateViable(*CorrectionValidator, Candidate)) { if (SearchNamespaces) QualifiedResults.push_back(Candidate); break; } Candidate.setCorrectionRange(SS.get(), Result.getLookupNameInfo()); return true; } return false; } void TypoCorrectionConsumer::performQualifiedLookups() { unsigned TypoLen = Typo->getName().size(); for (const TypoCorrection &QR : QualifiedResults) { for (const auto &NSI : Namespaces) { DeclContext *Ctx = NSI.DeclCtx; const Type *NSType = NSI.NameSpecifier->getAsType(); // If the current NestedNameSpecifier refers to a class and the // current correction candidate is the name of that class, then skip // it as it is unlikely a qualified version of the class' constructor // is an appropriate correction. if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() : nullptr) { if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo()) continue; } TypoCorrection TC(QR); TC.ClearCorrectionDecls(); TC.setCorrectionSpecifier(NSI.NameSpecifier); TC.setQualifierDistance(NSI.EditDistance); TC.setCallbackDistance(0); // Reset the callback distance // If the current correction candidate and namespace combination are // too far away from the original typo based on the normalized edit // distance, then skip performing a qualified name lookup. unsigned TmpED = TC.getEditDistance(true); if (QR.getCorrectionAsIdentifierInfo() != Typo && TmpED && TypoLen / TmpED < 3) continue; Result.clear(); Result.setLookupName(QR.getCorrectionAsIdentifierInfo()); if (!SemaRef.LookupQualifiedName(Result, Ctx)) continue; // Any corrections added below will be validated in subsequent // iterations of the main while() loop over the Consumer's contents. switch (Result.getResultKind()) { case LookupResult::Found: case LookupResult::FoundOverloaded: { if (SS && SS->isValid()) { std::string NewQualified = TC.getAsString(SemaRef.getLangOpts()); std::string OldQualified; llvm::raw_string_ostream OldOStream(OldQualified); SS->getScopeRep()->print(OldOStream, SemaRef.getPrintingPolicy()); OldOStream << Typo->getName(); // If correction candidate would be an identical written qualified // identifer, then the existing CXXScopeSpec probably included a // typedef that didn't get accounted for properly. if (OldOStream.str() == NewQualified) break; } for (LookupResult::iterator TRD = Result.begin(), TRDEnd = Result.end(); TRD != TRDEnd; ++TRD) { if (SemaRef.CheckMemberAccess(TC.getCorrectionRange().getBegin(), NSType ? NSType->getAsCXXRecordDecl() : nullptr, TRD.getPair()) == Sema::AR_accessible) TC.addCorrectionDecl(*TRD); } if (TC.isResolved()) { TC.setCorrectionRange(SS.get(), Result.getLookupNameInfo()); addCorrection(TC); } break; } case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::Ambiguous: case LookupResult::FoundUnresolvedValue: break; } } } QualifiedResults.clear(); } TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec) : Context(Context), CurContextChain(buildContextChain(CurContext)) { if (NestedNameSpecifier *NNS = CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) { llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier); NNS->print(SpecifierOStream, Context.getPrintingPolicy()); getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers); } // Build the list of identifiers that would be used for an absolute // (from the global context) NestedNameSpecifier referring to the current // context. for (DeclContext *C : llvm::reverse(CurContextChain)) { if (auto *ND = dyn_cast_or_null(C)) CurContextIdentifiers.push_back(ND->getIdentifier()); } // Add the global context as a NestedNameSpecifier SpecifierInfo SI = {cast(Context.getTranslationUnitDecl()), NestedNameSpecifier::GlobalSpecifier(Context), 1}; DistanceMap[1].push_back(SI); } auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain( DeclContext *Start) -> DeclContextList { assert(Start && "Building a context chain from a null context"); DeclContextList Chain; for (DeclContext *DC = Start->getPrimaryContext(); DC != nullptr; DC = DC->getLookupParent()) { NamespaceDecl *ND = dyn_cast_or_null(DC); if (!DC->isInlineNamespace() && !DC->isTransparentContext() && !(ND && ND->isAnonymousNamespace())) Chain.push_back(DC->getPrimaryContext()); } return Chain; } unsigned TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier( DeclContextList &DeclChain, NestedNameSpecifier *&NNS) { unsigned NumSpecifiers = 0; for (DeclContext *C : llvm::reverse(DeclChain)) { if (auto *ND = dyn_cast_or_null(C)) { NNS = NestedNameSpecifier::Create(Context, NNS, ND); ++NumSpecifiers; } else if (auto *RD = dyn_cast_or_null(C)) { NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(), RD->getTypeForDecl()); ++NumSpecifiers; } } return NumSpecifiers; } void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( DeclContext *Ctx) { NestedNameSpecifier *NNS = nullptr; unsigned NumSpecifiers = 0; DeclContextList NamespaceDeclChain(buildContextChain(Ctx)); DeclContextList FullNamespaceDeclChain(NamespaceDeclChain); // Eliminate common elements from the two DeclContext chains. for (DeclContext *C : llvm::reverse(CurContextChain)) { if (NamespaceDeclChain.empty() || NamespaceDeclChain.back() != C) break; NamespaceDeclChain.pop_back(); } // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain NumSpecifiers = buildNestedNameSpecifier(NamespaceDeclChain, NNS); // Add an explicit leading '::' specifier if needed. if (NamespaceDeclChain.empty()) { // Rebuild the NestedNameSpecifier as a globally-qualified specifier. NNS = NestedNameSpecifier::GlobalSpecifier(Context); NumSpecifiers = buildNestedNameSpecifier(FullNamespaceDeclChain, NNS); } else if (NamedDecl *ND = dyn_cast_or_null(NamespaceDeclChain.back())) { IdentifierInfo *Name = ND->getIdentifier(); bool SameNameSpecifier = false; if (std::find(CurNameSpecifierIdentifiers.begin(), CurNameSpecifierIdentifiers.end(), Name) != CurNameSpecifierIdentifiers.end()) { std::string NewNameSpecifier; llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier); SmallVector NewNameSpecifierIdentifiers; getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); NNS->print(SpecifierOStream, Context.getPrintingPolicy()); SpecifierOStream.flush(); SameNameSpecifier = NewNameSpecifier == CurNameSpecifier; } if (SameNameSpecifier || std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), Name) != CurContextIdentifiers.end()) { // Rebuild the NestedNameSpecifier as a globally-qualified specifier. NNS = NestedNameSpecifier::GlobalSpecifier(Context); NumSpecifiers = buildNestedNameSpecifier(FullNamespaceDeclChain, NNS); } } // If the built NestedNameSpecifier would be replacing an existing // NestedNameSpecifier, use the number of component identifiers that // would need to be changed as the edit distance instead of the number // of components in the built NestedNameSpecifier. if (NNS && !CurNameSpecifierIdentifiers.empty()) { SmallVector NewNameSpecifierIdentifiers; getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); NumSpecifiers = llvm::ComputeEditDistance( llvm::makeArrayRef(CurNameSpecifierIdentifiers), llvm::makeArrayRef(NewNameSpecifierIdentifiers)); } SpecifierInfo SI = {Ctx, NNS, NumSpecifiers}; DistanceMap[NumSpecifiers].push_back(SI); } /// \brief Perform name lookup for a possible result for typo correction. static void LookupPotentialTypoResult(Sema &SemaRef, LookupResult &Res, IdentifierInfo *Name, Scope *S, CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, bool isObjCIvarLookup, bool FindHidden) { Res.suppressDiagnostics(); Res.clear(); Res.setLookupName(Name); Res.setAllowHidden(FindHidden); if (MemberContext) { if (ObjCInterfaceDecl *Class = dyn_cast(MemberContext)) { if (isObjCIvarLookup) { if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) { Res.addDecl(Ivar); Res.resolveKind(); return; } } if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration( Name, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { Res.addDecl(Prop); Res.resolveKind(); return; } } SemaRef.LookupQualifiedName(Res, MemberContext); return; } SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, EnteringContext); // Fake ivar lookup; this should really be part of // LookupParsedName. if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { if (Method->isInstanceMethod() && Method->getClassInterface() && (Res.empty() || (Res.isSingleResult() && Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) { if (ObjCIvarDecl *IV = Method->getClassInterface()->lookupInstanceVariable(Name)) { Res.addDecl(IV); Res.resolveKind(); } } } } /// \brief Add keywords to the consumer as possible typo corrections. static void AddKeywordsToConsumer(Sema &SemaRef, TypoCorrectionConsumer &Consumer, Scope *S, CorrectionCandidateCallback &CCC, bool AfterNestedNameSpecifier) { if (AfterNestedNameSpecifier) { // For 'X::', we know exactly which keywords can appear next. Consumer.addKeywordResult("template"); if (CCC.WantExpressionKeywords) Consumer.addKeywordResult("operator"); return; } if (CCC.WantObjCSuper) Consumer.addKeywordResult("super"); if (CCC.WantTypeSpecifiers) { // Add type-specifier keywords to the set of results. static const char *const CTypeSpecs[] = { "char", "const", "double", "enum", "float", "int", "long", "short", "signed", "struct", "union", "unsigned", "void", "volatile", "_Complex", "_Imaginary", // storage-specifiers as well "extern", "inline", "static", "typedef" }; const unsigned NumCTypeSpecs = llvm::array_lengthof(CTypeSpecs); for (unsigned I = 0; I != NumCTypeSpecs; ++I) Consumer.addKeywordResult(CTypeSpecs[I]); if (SemaRef.getLangOpts().C99) Consumer.addKeywordResult("restrict"); if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) Consumer.addKeywordResult("bool"); else if (SemaRef.getLangOpts().C99) Consumer.addKeywordResult("_Bool"); if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("class"); Consumer.addKeywordResult("typename"); Consumer.addKeywordResult("wchar_t"); if (SemaRef.getLangOpts().CPlusPlus11) { Consumer.addKeywordResult("char16_t"); Consumer.addKeywordResult("char32_t"); Consumer.addKeywordResult("constexpr"); Consumer.addKeywordResult("decltype"); Consumer.addKeywordResult("thread_local"); } } if (SemaRef.getLangOpts().GNUMode) Consumer.addKeywordResult("typeof"); } else if (CCC.WantFunctionLikeCasts) { static const char *const CastableTypeSpecs[] = { "char", "double", "float", "int", "long", "short", "signed", "unsigned", "void" }; for (auto *kw : CastableTypeSpecs) Consumer.addKeywordResult(kw); } if (CCC.WantCXXNamedCasts && SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("const_cast"); Consumer.addKeywordResult("dynamic_cast"); Consumer.addKeywordResult("reinterpret_cast"); Consumer.addKeywordResult("static_cast"); } if (CCC.WantExpressionKeywords) { Consumer.addKeywordResult("sizeof"); if (SemaRef.getLangOpts().Bool || SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("false"); Consumer.addKeywordResult("true"); } if (SemaRef.getLangOpts().CPlusPlus) { static const char *const CXXExprs[] = { "delete", "new", "operator", "throw", "typeid" }; const unsigned NumCXXExprs = llvm::array_lengthof(CXXExprs); for (unsigned I = 0; I != NumCXXExprs; ++I) Consumer.addKeywordResult(CXXExprs[I]); if (isa(SemaRef.CurContext) && cast(SemaRef.CurContext)->isInstance()) Consumer.addKeywordResult("this"); if (SemaRef.getLangOpts().CPlusPlus11) { Consumer.addKeywordResult("alignof"); Consumer.addKeywordResult("nullptr"); } } if (SemaRef.getLangOpts().C11) { // FIXME: We should not suggest _Alignof if the alignof macro // is present. Consumer.addKeywordResult("_Alignof"); } } if (CCC.WantRemainingKeywords) { if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) { // Statements. static const char *const CStmts[] = { "do", "else", "for", "goto", "if", "return", "switch", "while" }; const unsigned NumCStmts = llvm::array_lengthof(CStmts); for (unsigned I = 0; I != NumCStmts; ++I) Consumer.addKeywordResult(CStmts[I]); if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("catch"); Consumer.addKeywordResult("try"); } if (S && S->getBreakParent()) Consumer.addKeywordResult("break"); if (S && S->getContinueParent()) Consumer.addKeywordResult("continue"); if (!SemaRef.getCurFunction()->SwitchStack.empty()) { Consumer.addKeywordResult("case"); Consumer.addKeywordResult("default"); } } else { if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("namespace"); Consumer.addKeywordResult("template"); } if (S && S->isClassScope()) { Consumer.addKeywordResult("explicit"); Consumer.addKeywordResult("friend"); Consumer.addKeywordResult("mutable"); Consumer.addKeywordResult("private"); Consumer.addKeywordResult("protected"); Consumer.addKeywordResult("public"); Consumer.addKeywordResult("virtual"); } } if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("using"); if (SemaRef.getLangOpts().CPlusPlus11) Consumer.addKeywordResult("static_assert"); } } } std::unique_ptr Sema::makeTypoCorrectionConsumer( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, std::unique_ptr CCC, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, bool ErrorRecovery) { if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking || DisableTypoCorrection) return nullptr; // In Microsoft mode, don't perform typo correction in a template member // function dependent context because it interferes with the "lookup into // dependent bases of class templates" feature. if (getLangOpts().MSVCCompat && CurContext->isDependentContext() && isa(CurContext)) return nullptr; // We only attempt to correct typos for identifiers. IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo(); if (!Typo) return nullptr; // If the scope specifier itself was invalid, don't try to correct // typos. if (SS && SS->isInvalid()) return nullptr; // Never try to correct typos during template deduction or // instantiation. if (!ActiveTemplateInstantiations.empty()) return nullptr; // Don't try to correct 'super'. if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier()) return nullptr; // Abort if typo correction already failed for this specific typo. IdentifierSourceLocations::iterator locs = TypoCorrectionFailures.find(Typo); if (locs != TypoCorrectionFailures.end() && locs->second.count(TypoName.getLoc())) return nullptr; // Don't try to correct the identifier "vector" when in AltiVec mode. // TODO: Figure out why typo correction misbehaves in this case, fix it, and // remove this workaround. if ((getLangOpts().AltiVec || getLangOpts().ZVector) && Typo->isStr("vector")) return nullptr; // Provide a stop gap for files that are just seriously broken. Trying // to correct all typos can turn into a HUGE performance penalty, causing // some files to take minutes to get rejected by the parser. unsigned Limit = getDiagnostics().getDiagnosticOptions().SpellCheckingLimit; if (Limit && TyposCorrected >= Limit) return nullptr; ++TyposCorrected; // If we're handling a missing symbol error, using modules, and the // special search all modules option is used, look for a missing import. if (ErrorRecovery && getLangOpts().Modules && getLangOpts().ModulesSearchAll) { // The following has the side effect of loading the missing module. getModuleLoader().lookupMissingImports(Typo->getName(), TypoName.getLocStart()); } CorrectionCandidateCallback &CCCRef = *CCC; auto Consumer = llvm::make_unique( *this, TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, EnteringContext); // Perform name lookup to find visible, similarly-named entities. bool IsUnqualifiedLookup = false; DeclContext *QualifiedDC = MemberContext; if (MemberContext) { LookupVisibleDecls(MemberContext, LookupKind, *Consumer); // Look in qualified interfaces. if (OPT) { for (auto *I : OPT->quals()) LookupVisibleDecls(I, LookupKind, *Consumer); } } else if (SS && SS->isSet()) { QualifiedDC = computeDeclContext(*SS, EnteringContext); if (!QualifiedDC) return nullptr; LookupVisibleDecls(QualifiedDC, LookupKind, *Consumer); } else { IsUnqualifiedLookup = true; } // Determine whether we are going to search in the various namespaces for // corrections. bool SearchNamespaces = getLangOpts().CPlusPlus && (IsUnqualifiedLookup || (SS && SS->isSet())); if (IsUnqualifiedLookup || SearchNamespaces) { // For unqualified lookup, look through all of the names that we have // seen in this translation unit. // FIXME: Re-add the ability to skip very unlikely potential corrections. for (const auto &I : Context.Idents) Consumer->FoundName(I.getKey()); // Walk through identifiers in external identifier sources. // FIXME: Re-add the ability to skip very unlikely potential corrections. if (IdentifierInfoLookup *External = Context.Idents.getExternalIdentifierLookup()) { std::unique_ptr Iter(External->getIdentifiers()); do { StringRef Name = Iter->Next(); if (Name.empty()) break; Consumer->FoundName(Name); } while (true); } } AddKeywordsToConsumer(*this, *Consumer, S, CCCRef, SS && SS->isNotEmpty()); // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going // to search those namespaces. if (SearchNamespaces) { // Load any externally-known namespaces. if (ExternalSource && !LoadedExternalKnownNamespaces) { SmallVector ExternalKnownNamespaces; LoadedExternalKnownNamespaces = true; ExternalSource->ReadKnownNamespaces(ExternalKnownNamespaces); for (auto *N : ExternalKnownNamespaces) KnownNamespaces[N] = true; } Consumer->addNamespaces(KnownNamespaces); } return Consumer; } /// \brief Try to "correct" a typo in the source code by finding /// visible declarations whose names are similar to the name that was /// present in the source code. /// /// \param TypoName the \c DeclarationNameInfo structure that contains /// the name that was present in the source code along with its location. /// /// \param LookupKind the name-lookup criteria used to search for the name. /// /// \param S the scope in which name lookup occurs. /// /// \param SS the nested-name-specifier that precedes the name we're /// looking for, if present. /// /// \param CCC A CorrectionCandidateCallback object that provides further /// validation of typo correction candidates. It also provides flags for /// determining the set of keywords permitted. /// /// \param MemberContext if non-NULL, the context in which to look for /// a member access expression. /// /// \param EnteringContext whether we're entering the context described by /// the nested-name-specifier SS. /// /// \param OPT when non-NULL, the search for visible declarations will /// also walk the protocols in the qualified interfaces of \p OPT. /// /// \returns a \c TypoCorrection containing the corrected name if the typo /// along with information such as the \c NamedDecl where the corrected name /// was declared, and any additional \c NestedNameSpecifier needed to access /// it (C++ only). The \c TypoCorrection is empty if there is no correction. TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, std::unique_ptr CCC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT, bool RecordFailure) { assert(CCC && "CorrectTypo requires a CorrectionCandidateCallback"); // Always let the ExternalSource have the first chance at correction, even // if we would otherwise have given up. if (ExternalSource) { if (TypoCorrection Correction = ExternalSource->CorrectTypo( TypoName, LookupKind, S, SS, *CCC, MemberContext, EnteringContext, OPT)) return Correction; } // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver; // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for // some instances of CTC_Unknown, while WantRemainingKeywords is true // for CTC_Unknown but not for CTC_ObjCMessageReceiver. bool ObjCMessageReceiver = CCC->WantObjCSuper && !CCC->WantRemainingKeywords; IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo(); auto Consumer = makeTypoCorrectionConsumer( TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, EnteringContext, OPT, Mode == CTK_ErrorRecovery); if (!Consumer) return TypoCorrection(); // If we haven't found anything, we're done. if (Consumer->empty()) return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); // Make sure the best edit distance (prior to adding any namespace qualifiers) // is not more that about a third of the length of the typo's identifier. unsigned ED = Consumer->getBestEditDistance(true); unsigned TypoLen = Typo->getName().size(); if (ED > 0 && TypoLen / ED < 3) return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); TypoCorrection BestTC = Consumer->getNextCorrection(); TypoCorrection SecondBestTC = Consumer->getNextCorrection(); if (!BestTC) return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); ED = BestTC.getEditDistance(); if (TypoLen >= 3 && ED > 0 && TypoLen / ED < 3) { // If this was an unqualified lookup and we believe the callback // object wouldn't have filtered out possible corrections, note // that no correction was found. return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); } // If only a single name remains, return that result. if (!SecondBestTC || SecondBestTC.getEditDistance(false) > BestTC.getEditDistance(false)) { const TypoCorrection &Result = BestTC; // Don't correct to a keyword that's the same as the typo; the keyword // wasn't actually in scope. if (ED == 0 && Result.isKeyword()) return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); TypoCorrection TC = Result; TC.setCorrectionRange(SS, TypoName); checkCorrectionVisibility(*this, TC); return TC; } else if (SecondBestTC && ObjCMessageReceiver) { // Prefer 'super' when we're completing in a message-receiver // context. if (BestTC.getCorrection().getAsString() != "super") { if (SecondBestTC.getCorrection().getAsString() == "super") BestTC = SecondBestTC; else if ((*Consumer)["super"].front().isKeyword()) BestTC = (*Consumer)["super"].front(); } // Don't correct to a keyword that's the same as the typo; the keyword // wasn't actually in scope. if (BestTC.getEditDistance() == 0 || BestTC.getCorrection().getAsString() != "super") return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure); BestTC.setCorrectionRange(SS, TypoName); return BestTC; } // Record the failure's location if needed and return an empty correction. If // this was an unqualified lookup and we believe the callback object did not // filter out possible corrections, also cache the failure for the typo. return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC); } /// \brief Try to "correct" a typo in the source code by finding /// visible declarations whose names are similar to the name that was /// present in the source code. /// /// \param TypoName the \c DeclarationNameInfo structure that contains /// the name that was present in the source code along with its location. /// /// \param LookupKind the name-lookup criteria used to search for the name. /// /// \param S the scope in which name lookup occurs. /// /// \param SS the nested-name-specifier that precedes the name we're /// looking for, if present. /// /// \param CCC A CorrectionCandidateCallback object that provides further /// validation of typo correction candidates. It also provides flags for /// determining the set of keywords permitted. /// /// \param TDG A TypoDiagnosticGenerator functor that will be used to print /// diagnostics when the actual typo correction is attempted. /// /// \param TRC A TypoRecoveryCallback functor that will be used to build an /// Expr from a typo correction candidate. /// /// \param MemberContext if non-NULL, the context in which to look for /// a member access expression. /// /// \param EnteringContext whether we're entering the context described by /// the nested-name-specifier SS. /// /// \param OPT when non-NULL, the search for visible declarations will /// also walk the protocols in the qualified interfaces of \p OPT. /// /// \returns a new \c TypoExpr that will later be replaced in the AST with an /// Expr representing the result of performing typo correction, or nullptr if /// typo correction is not possible. If nullptr is returned, no diagnostics will /// be emitted and it is the responsibility of the caller to emit any that are /// needed. TypoExpr *Sema::CorrectTypoDelayed( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, std::unique_ptr CCC, TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT) { assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback"); auto Consumer = makeTypoCorrectionConsumer( TypoName, LookupKind, S, SS, std::move(CCC), MemberContext, EnteringContext, OPT, Mode == CTK_ErrorRecovery); // Give the external sema source a chance to correct the typo. TypoCorrection ExternalTypo; if (ExternalSource && Consumer) { ExternalTypo = ExternalSource->CorrectTypo( TypoName, LookupKind, S, SS, *Consumer->getCorrectionValidator(), MemberContext, EnteringContext, OPT); if (ExternalTypo) Consumer->addCorrection(ExternalTypo); } if (!Consumer || Consumer->empty()) return nullptr; // Make sure the best edit distance (prior to adding any namespace qualifiers) // is not more that about a third of the length of the typo's identifier. unsigned ED = Consumer->getBestEditDistance(true); IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo(); if (!ExternalTypo && ED > 0 && Typo->getName().size() / ED < 3) return nullptr; ExprEvalContexts.back().NumTypos++; return createDelayedTypo(std::move(Consumer), std::move(TDG), std::move(TRC)); } void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) { if (!CDecl) return; if (isKeyword()) CorrectionDecls.clear(); CorrectionDecls.push_back(CDecl); if (!CorrectionName) CorrectionName = CDecl->getDeclName(); } std::string TypoCorrection::getAsString(const LangOptions &LO) const { if (CorrectionNameSpec) { std::string tmpBuffer; llvm::raw_string_ostream PrefixOStream(tmpBuffer); CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO)); PrefixOStream << CorrectionName; return PrefixOStream.str(); } return CorrectionName.getAsString(); } bool CorrectionCandidateCallback::ValidateCandidate( const TypoCorrection &candidate) { if (!candidate.isResolved()) return true; if (candidate.isKeyword()) return WantTypeSpecifiers || WantExpressionKeywords || WantCXXNamedCasts || WantRemainingKeywords || WantObjCSuper; bool HasNonType = false; bool HasStaticMethod = false; bool HasNonStaticMethod = false; for (Decl *D : candidate) { if (FunctionTemplateDecl *FTD = dyn_cast(D)) D = FTD->getTemplatedDecl(); if (CXXMethodDecl *Method = dyn_cast(D)) { if (Method->isStatic()) HasStaticMethod = true; else HasNonStaticMethod = true; } if (!isa(D)) HasNonType = true; } if (IsAddressOfOperand && HasNonStaticMethod && !HasStaticMethod && !candidate.getCorrectionSpecifier()) return false; return WantTypeSpecifiers || HasNonType; } FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, bool HasExplicitTemplateArgs, MemberExpr *ME) : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs), CurContext(SemaRef.CurContext), MemberFn(ME) { WantTypeSpecifiers = false; WantFunctionLikeCasts = SemaRef.getLangOpts().CPlusPlus && NumArgs == 1; WantRemainingKeywords = false; } bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) { if (!candidate.getCorrectionDecl()) return candidate.isKeyword(); for (auto *C : candidate) { FunctionDecl *FD = nullptr; NamedDecl *ND = C->getUnderlyingDecl(); if (FunctionTemplateDecl *FTD = dyn_cast(ND)) FD = FTD->getTemplatedDecl(); if (!HasExplicitTemplateArgs && !FD) { if (!(FD = dyn_cast(ND)) && isa(ND)) { // If the Decl is neither a function nor a template function, // determine if it is a pointer or reference to a function. If so, // check against the number of arguments expected for the pointee. QualType ValType = cast(ND)->getType(); if (ValType->isAnyPointerType() || ValType->isReferenceType()) ValType = ValType->getPointeeType(); if (const FunctionProtoType *FPT = ValType->getAs()) if (FPT->getNumParams() == NumArgs) return true; } } // Skip the current candidate if it is not a FunctionDecl or does not accept // the current number of arguments. if (!FD || !(FD->getNumParams() >= NumArgs && FD->getMinRequiredArguments() <= NumArgs)) continue; // If the current candidate is a non-static C++ method, skip the candidate // unless the method being corrected--or the current DeclContext, if the // function being corrected is not a method--is a method in the same class // or a descendent class of the candidate's parent class. if (CXXMethodDecl *MD = dyn_cast(FD)) { if (MemberFn || !MD->isStatic()) { CXXMethodDecl *CurMD = MemberFn ? dyn_cast_or_null(MemberFn->getMemberDecl()) : dyn_cast_or_null(CurContext); CXXRecordDecl *CurRD = CurMD ? CurMD->getParent()->getCanonicalDecl() : nullptr; CXXRecordDecl *RD = MD->getParent()->getCanonicalDecl(); if (!CurRD || (CurRD != RD && !CurRD->isDerivedFrom(RD))) continue; } } return true; } return false; } void Sema::diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery) { diagnoseTypo(Correction, TypoDiag, PDiag(diag::note_previous_decl), ErrorRecovery); } /// Find which declaration we should import to provide the definition of /// the given declaration. static NamedDecl *getDefinitionToImport(NamedDecl *D) { if (VarDecl *VD = dyn_cast(D)) return VD->getDefinition(); if (FunctionDecl *FD = dyn_cast(D)) return FD->getDefinition(); if (TagDecl *TD = dyn_cast(D)) return TD->getDefinition(); if (ObjCInterfaceDecl *ID = dyn_cast(D)) return ID->getDefinition(); if (ObjCProtocolDecl *PD = dyn_cast(D)) return PD->getDefinition(); if (TemplateDecl *TD = dyn_cast(D)) return getDefinitionToImport(TD->getTemplatedDecl()); return nullptr; } void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, MissingImportKind MIK, bool Recover) { assert(!isVisible(Decl) && "missing import for non-hidden decl?"); // Suggest importing a module providing the definition of this entity, if // possible. NamedDecl *Def = getDefinitionToImport(Decl); if (!Def) Def = Decl; Module *Owner = getOwningModule(Decl); assert(Owner && "definition of hidden declaration is not in a module"); llvm::SmallVector OwningModules; OwningModules.push_back(Owner); auto Merged = Context.getModulesWithMergedDefinition(Decl); OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end()); diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, MIK, Recover); } /// \brief Get a "quoted.h" or include path to use in a diagnostic /// suggesting the addition of a #include of the specified file. static std::string getIncludeStringForHeader(Preprocessor &PP, const FileEntry *E) { bool IsSystem; auto Path = PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(E, &IsSystem); return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"'); } void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl, SourceLocation DeclLoc, ArrayRef Modules, MissingImportKind MIK, bool Recover) { assert(!Modules.empty()); if (Modules.size() > 1) { std::string ModuleList; unsigned N = 0; for (Module *M : Modules) { ModuleList += "\n "; if (++N == 5 && N != Modules.size()) { ModuleList += "[...]"; break; } ModuleList += M->getFullModuleName(); } Diag(UseLoc, diag::err_module_unimported_use_multiple) << (int)MIK << Decl << ModuleList; } else if (const FileEntry *E = PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) { // The right way to make the declaration visible is to include a header; // suggest doing so. // // FIXME: Find a smart place to suggest inserting a #include, and add // a FixItHint there. Diag(UseLoc, diag::err_module_unimported_use_header) << (int)MIK << Decl << Modules[0]->getFullModuleName() << getIncludeStringForHeader(PP, E); } else { // FIXME: Add a FixItHint that imports the corresponding module. Diag(UseLoc, diag::err_module_unimported_use) << (int)MIK << Decl << Modules[0]->getFullModuleName(); } unsigned DiagID; switch (MIK) { case MissingImportKind::Declaration: DiagID = diag::note_previous_declaration; break; case MissingImportKind::Definition: DiagID = diag::note_previous_definition; break; case MissingImportKind::DefaultArgument: DiagID = diag::note_default_argument_declared_here; break; case MissingImportKind::ExplicitSpecialization: DiagID = diag::note_explicit_specialization_declared_here; break; case MissingImportKind::PartialSpecialization: DiagID = diag::note_partial_specialization_declared_here; break; } Diag(DeclLoc, DiagID); // Try to recover by implicitly importing this module. if (Recover) createImplicitModuleImportForErrorRecovery(UseLoc, Modules[0]); } /// \brief Diagnose a successfully-corrected typo. Separated from the correction /// itself to allow external validation of the result, etc. /// /// \param Correction The result of performing typo correction. /// \param TypoDiag The diagnostic to produce. This will have the corrected /// string added to it (and usually also a fixit). /// \param PrevNote A note to use when indicating the location of the entity to /// which we are correcting. Will have the correction string added to it. /// \param ErrorRecovery If \c true (the default), the caller is going to /// recover from the typo as if the corrected string had been typed. /// In this case, \c PDiag must be an error, and we will attach a fixit /// to it. void Sema::diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, const PartialDiagnostic &PrevNote, bool ErrorRecovery) { std::string CorrectedStr = Correction.getAsString(getLangOpts()); std::string CorrectedQuotedStr = Correction.getQuoted(getLangOpts()); FixItHint FixTypo = FixItHint::CreateReplacement( Correction.getCorrectionRange(), CorrectedStr); // Maybe we're just missing a module import. if (Correction.requiresImport()) { NamedDecl *Decl = Correction.getFoundDecl(); assert(Decl && "import required but no declaration to import"); diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl, MissingImportKind::Declaration, ErrorRecovery); return; } Diag(Correction.getCorrectionRange().getBegin(), TypoDiag) << CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint()); NamedDecl *ChosenDecl = Correction.isKeyword() ? nullptr : Correction.getFoundDecl(); if (PrevNote.getDiagID() && ChosenDecl) Diag(ChosenDecl->getLocation(), PrevNote) << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo); // Add any extra diagnostics. for (const PartialDiagnostic &PD : Correction.getExtraDiagnostics()) Diag(Correction.getCorrectionRange().getBegin(), PD); } TypoExpr *Sema::createDelayedTypo(std::unique_ptr TCC, TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC) { assert(TCC && "createDelayedTypo requires a valid TypoCorrectionConsumer"); auto TE = new (Context) TypoExpr(Context.DependentTy); auto &State = DelayedTypos[TE]; State.Consumer = std::move(TCC); State.DiagHandler = std::move(TDG); State.RecoveryHandler = std::move(TRC); return TE; } const Sema::TypoExprState &Sema::getTypoExprState(TypoExpr *TE) const { auto Entry = DelayedTypos.find(TE); assert(Entry != DelayedTypos.end() && "Failed to get the state for a TypoExpr!"); return Entry->second; } void Sema::clearDelayedTypo(TypoExpr *TE) { DelayedTypos.erase(TE); } void Sema::ActOnPragmaDump(Scope *S, SourceLocation IILoc, IdentifierInfo *II) { DeclarationNameInfo Name(II, IILoc); LookupResult R(*this, Name, LookupAnyName, Sema::NotForRedeclaration); R.suppressDiagnostics(); R.setHideTags(false); LookupName(R, S); R.dump(); } Index: vendor/clang/dist/lib/Sema/SemaStmt.cpp =================================================================== --- vendor/clang/dist/lib/Sema/SemaStmt.cpp (revision 313882) +++ vendor/clang/dist/lib/Sema/SemaStmt.cpp (revision 313883) @@ -1,4010 +1,4012 @@ //===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements semantic analysis for statements. // //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" using namespace clang; using namespace sema; StmtResult Sema::ActOnExprStmt(ExprResult FE) { if (FE.isInvalid()) return StmtError(); FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), /*DiscardedValue*/ true); if (FE.isInvalid()) return StmtError(); // C99 6.8.3p2: The expression in an expression statement is evaluated as a // void expression for its side effects. Conversion to void allows any // operand, even incomplete types. // Same thing in for stmt first clause (when expr) and third clause. return StmtResult(FE.getAs()); } StmtResult Sema::ActOnExprStmtError() { DiscardCleanupsInEvaluationContext(); return StmtError(); } StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro) { return new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro); } StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, SourceLocation EndLoc) { DeclGroupRef DG = dg.get(); // If we have an invalid decl, just return an error. if (DG.isNull()) return StmtError(); return new (Context) DeclStmt(DG, StartLoc, EndLoc); } void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { DeclGroupRef DG = dg.get(); // If we don't have a declaration, or we have an invalid declaration, // just return. if (DG.isNull() || !DG.isSingleDecl()) return; Decl *decl = DG.getSingleDecl(); if (!decl || decl->isInvalidDecl()) return; // Only variable declarations are permitted. VarDecl *var = dyn_cast(decl); if (!var) { Diag(decl->getLocation(), diag::err_non_variable_decl_in_for); decl->setInvalidDecl(); return; } // foreach variables are never actually initialized in the way that // the parser came up with. var->setInit(nullptr); // In ARC, we don't need to retain the iteration variable of a fast // enumeration loop. Rather than actually trying to catch that // during declaration processing, we remove the consequences here. if (getLangOpts().ObjCAutoRefCount) { QualType type = var->getType(); // Only do this if we inferred the lifetime. Inferred lifetime // will show up as a local qualifier because explicit lifetime // should have shown up as an AttributedType instead. if (type.getLocalQualifiers().getObjCLifetime() == Qualifiers::OCL_Strong) { // Add 'const' and mark the variable as pseudo-strong. var->setType(type.withConst()); var->setARCPseudoStrong(true); } } } /// \brief Diagnose unused comparisons, both builtin and overloaded operators. /// For '==' and '!=', suggest fixits for '=' or '|='. /// /// Adding a cast to void (or other expression wrappers) will prevent the /// warning from firing. static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) { SourceLocation Loc; bool IsNotEqual, CanAssign, IsRelational; if (const BinaryOperator *Op = dyn_cast(E)) { if (!Op->isComparisonOp()) return false; IsRelational = Op->isRelationalOp(); Loc = Op->getOperatorLoc(); IsNotEqual = Op->getOpcode() == BO_NE; CanAssign = Op->getLHS()->IgnoreParenImpCasts()->isLValue(); } else if (const CXXOperatorCallExpr *Op = dyn_cast(E)) { switch (Op->getOperator()) { default: return false; case OO_EqualEqual: case OO_ExclaimEqual: IsRelational = false; break; case OO_Less: case OO_Greater: case OO_GreaterEqual: case OO_LessEqual: IsRelational = true; break; } Loc = Op->getOperatorLoc(); IsNotEqual = Op->getOperator() == OO_ExclaimEqual; CanAssign = Op->getArg(0)->IgnoreParenImpCasts()->isLValue(); } else { // Not a typo-prone comparison. return false; } // Suppress warnings when the operator, suspicious as it may be, comes from // a macro expansion. if (S.SourceMgr.isMacroBodyExpansion(Loc)) return false; S.Diag(Loc, diag::warn_unused_comparison) << (unsigned)IsRelational << (unsigned)IsNotEqual << E->getSourceRange(); // If the LHS is a plausible entity to assign to, provide a fixit hint to // correct common typos. if (!IsRelational && CanAssign) { if (IsNotEqual) S.Diag(Loc, diag::note_inequality_comparison_to_or_assign) << FixItHint::CreateReplacement(Loc, "|="); else S.Diag(Loc, diag::note_equality_comparison_to_assign) << FixItHint::CreateReplacement(Loc, "="); } return true; } void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (const LabelStmt *Label = dyn_cast_or_null(S)) return DiagnoseUnusedExprResult(Label->getSubStmt()); const Expr *E = dyn_cast_or_null(S); if (!E) return; // If we are in an unevaluated expression context, then there can be no unused // results because the results aren't expected to be used in the first place. if (isUnevaluatedContext()) return; SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc(); // In most cases, we don't want to warn if the expression is written in a // macro body, or if the macro comes from a system header. If the offending // expression is a call to a function with the warn_unused_result attribute, // we warn no matter the location. Because of the order in which the various // checks need to happen, we factor out the macro-related test here. bool ShouldSuppress = SourceMgr.isMacroBodyExpansion(ExprLoc) || SourceMgr.isInSystemMacro(ExprLoc); const Expr *WarnExpr; SourceLocation Loc; SourceRange R1, R2; if (!E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context)) return; // If this is a GNU statement expression expanded from a macro, it is probably // unused because it is a function-like macro that can be used as either an // expression or statement. Don't warn, because it is almost certainly a // false positive. if (isa(E) && Loc.isMacroID()) return; // Check if this is the UNREFERENCED_PARAMETER from the Microsoft headers. // That macro is frequently used to suppress "unused parameter" warnings, // but its implementation makes clang's -Wunused-value fire. Prevent this. if (isa(E->IgnoreImpCasts()) && Loc.isMacroID()) { SourceLocation SpellLoc = Loc; if (findMacroSpelling(SpellLoc, "UNREFERENCED_PARAMETER")) return; } // Okay, we have an unused result. Depending on what the base expression is, // we might want to make a more specific diagnostic. Check for one of these // cases now. unsigned DiagID = diag::warn_unused_expr; if (const ExprWithCleanups *Temps = dyn_cast(E)) E = Temps->getSubExpr(); if (const CXXBindTemporaryExpr *TempExpr = dyn_cast(E)) E = TempExpr->getSubExpr(); if (DiagnoseUnusedComparison(*this, E)) return; E = WarnExpr; if (const CallExpr *CE = dyn_cast(E)) { if (E->getType()->isVoidType()) return; // If the callee has attribute pure, const, or warn_unused_result, warn with // a more specific message to make it clear what is happening. If the call // is written in a macro body, only warn if it has the warn_unused_result // attribute. if (const Decl *FD = CE->getCalleeDecl()) { if (const Attr *A = isa(FD) ? cast(FD)->getUnusedResultAttr() : FD->getAttr()) { Diag(Loc, diag::warn_unused_result) << A << R1 << R2; return; } if (ShouldSuppress) return; if (FD->hasAttr()) { Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure"; return; } if (FD->hasAttr()) { Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const"; return; } } } else if (ShouldSuppress) return; if (const ObjCMessageExpr *ME = dyn_cast(E)) { if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) { Diag(Loc, diag::err_arc_unused_init_message) << R1; return; } const ObjCMethodDecl *MD = ME->getMethodDecl(); if (MD) { if (const auto *A = MD->getAttr()) { Diag(Loc, diag::warn_unused_result) << A << R1 << R2; return; } } } else if (const PseudoObjectExpr *POE = dyn_cast(E)) { const Expr *Source = POE->getSyntacticForm(); if (isa(Source)) DiagID = diag::warn_unused_container_subscript_expr; else DiagID = diag::warn_unused_property_expr; } else if (const CXXFunctionalCastExpr *FC = dyn_cast(E)) { if (isa(FC->getSubExpr()) || isa(FC->getSubExpr())) return; } // Diagnose "(void*) blah" as a typo for "(void) blah". else if (const CStyleCastExpr *CE = dyn_cast(E)) { TypeSourceInfo *TI = CE->getTypeInfoAsWritten(); QualType T = TI->getType(); // We really do want to use the non-canonical type here. if (T == Context.VoidPtrTy) { PointerTypeLoc TL = TI->getTypeLoc().castAs(); Diag(Loc, diag::warn_unused_voidptr) << FixItHint::CreateRemoval(TL.getStarLoc()); return; } } if (E->isGLValue() && E->getType().isVolatileQualified()) { Diag(Loc, diag::warn_unused_volatile) << R1 << R2; return; } DiagRuntimeBehavior(Loc, nullptr, PDiag(DiagID) << R1 << R2); } void Sema::ActOnStartOfCompoundStmt() { PushCompoundScope(); } void Sema::ActOnFinishOfCompoundStmt() { PopCompoundScope(); } sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { return getCurFunction()->CompoundScopes.back(); } StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); // If we're in C89 mode, check that we don't have any decls after stmts. If // so, emit an extension diagnostic. if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { // Note that __extension__ can be around a decl. unsigned i = 0; // Skip over all declarations. for (; i != NumElts && isa(Elts[i]); ++i) /*empty*/; // We found the end of the list or a statement. Scan for another declstmt. for (; i != NumElts && !isa(Elts[i]); ++i) /*empty*/; if (i != NumElts) { Decl *D = *cast(Elts[i])->decl_begin(); Diag(D->getLocation(), diag::ext_mixed_decls_code); } } // Warn about unused expressions in statements. for (unsigned i = 0; i != NumElts; ++i) { // Ignore statements that are last in a statement expression. if (isStmtExpr && i == NumElts - 1) continue; DiagnoseUnusedExprResult(Elts[i]); } // Check for suspicious empty body (null statement) in `for' and `while' // statements. Don't do anything for template instantiations, this just adds // noise. if (NumElts != 0 && !CurrentInstantiationScope && getCurCompoundScope().HasEmptyLoopBodies) { for (unsigned i = 0; i != NumElts - 1; ++i) DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); } return new (Context) CompoundStmt(Context, Elts, L, R); } StmtResult Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, SourceLocation DotDotDotLoc, Expr *RHSVal, SourceLocation ColonLoc) { assert(LHSVal && "missing expression in case statement"); if (getCurFunction()->SwitchStack.empty()) { Diag(CaseLoc, diag::err_case_not_in_switch); return StmtError(); } ExprResult LHS = CorrectDelayedTyposInExpr(LHSVal, [this](class Expr *E) { if (!getLangOpts().CPlusPlus11) return VerifyIntegerConstantExpression(E); if (Expr *CondExpr = getCurFunction()->SwitchStack.back()->getCond()) { QualType CondType = CondExpr->getType(); llvm::APSInt TempVal; return CheckConvertedConstantExpression(E, CondType, TempVal, CCEK_CaseValue); } return ExprError(); }); if (LHS.isInvalid()) return StmtError(); LHSVal = LHS.get(); if (!getLangOpts().CPlusPlus11) { // C99 6.8.4.2p3: The expression shall be an integer constant. // However, GCC allows any evaluatable integer expression. if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) { LHSVal = VerifyIntegerConstantExpression(LHSVal).get(); if (!LHSVal) return StmtError(); } // GCC extension: The expression shall be an integer constant. if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) { RHSVal = VerifyIntegerConstantExpression(RHSVal).get(); // Recover from an error by just forgetting about it. } } LHS = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false, getLangOpts().CPlusPlus11); if (LHS.isInvalid()) return StmtError(); auto RHS = RHSVal ? ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false, getLangOpts().CPlusPlus11) : ExprResult(); if (RHS.isInvalid()) return StmtError(); CaseStmt *CS = new (Context) CaseStmt(LHS.get(), RHS.get(), CaseLoc, DotDotDotLoc, ColonLoc); getCurFunction()->SwitchStack.back()->addSwitchCase(CS); return CS; } /// ActOnCaseStmtBody - This installs a statement as the body of a case. void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) { DiagnoseUnusedExprResult(SubStmt); CaseStmt *CS = static_cast(caseStmt); CS->setSubStmt(SubStmt); } StmtResult Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, Stmt *SubStmt, Scope *CurScope) { DiagnoseUnusedExprResult(SubStmt); if (getCurFunction()->SwitchStack.empty()) { Diag(DefaultLoc, diag::err_default_not_in_switch); return SubStmt; } DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt); getCurFunction()->SwitchStack.back()->addSwitchCase(DS); return DS; } StmtResult Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, SourceLocation ColonLoc, Stmt *SubStmt) { // If the label was multiply defined, reject it now. if (TheDecl->getStmt()) { Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName(); Diag(TheDecl->getLocation(), diag::note_previous_definition); return SubStmt; } // Otherwise, things are good. Fill in the declaration and return it. LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); TheDecl->setStmt(LS); if (!TheDecl->isGnuLocal()) { TheDecl->setLocStart(IdentLoc); if (!TheDecl->isMSAsmLabel()) { // Don't update the location of MS ASM labels. These will result in // a diagnostic, and changing the location here will mess that up. TheDecl->setLocation(IdentLoc); } } return LS; } StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc, ArrayRef Attrs, Stmt *SubStmt) { // Fill in the declaration and return it. AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt); return LS; } namespace { class CommaVisitor : public EvaluatedExprVisitor { typedef EvaluatedExprVisitor Inherited; Sema &SemaRef; public: CommaVisitor(Sema &SemaRef) : Inherited(SemaRef.Context), SemaRef(SemaRef) {} void VisitBinaryOperator(BinaryOperator *E) { if (E->getOpcode() == BO_Comma) SemaRef.DiagnoseCommaOperator(E->getLHS(), E->getExprLoc()); EvaluatedExprVisitor::VisitBinaryOperator(E); } }; } StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, ConditionResult Cond, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { if (Cond.isInvalid()) Cond = ConditionResult( *this, nullptr, MakeFullExpr(new (Context) OpaqueValueExpr(SourceLocation(), Context.BoolTy, VK_RValue), IfLoc), false); Expr *CondExpr = Cond.get().second; if (!Diags.isIgnored(diag::warn_comma_operator, CondExpr->getExprLoc())) CommaVisitor(*this).Visit(CondExpr); if (!elseStmt) DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), thenStmt, diag::warn_empty_if_body); return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc, elseStmt); } StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, Stmt *InitStmt, ConditionResult Cond, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { if (Cond.isInvalid()) return StmtError(); if (IsConstexpr || isa(Cond.get().second)) getCurFunction()->setHasBranchProtectedScope(); DiagnoseUnusedExprResult(thenStmt); DiagnoseUnusedExprResult(elseStmt); return new (Context) IfStmt(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, Cond.get().second, thenStmt, ElseLoc, elseStmt); } namespace { struct CaseCompareFunctor { bool operator()(const std::pair &LHS, const llvm::APSInt &RHS) { return LHS.first < RHS; } bool operator()(const std::pair &LHS, const std::pair &RHS) { return LHS.first < RHS.first; } bool operator()(const llvm::APSInt &LHS, const std::pair &RHS) { return LHS < RHS.first; } }; } /// CmpCaseVals - Comparison predicate for sorting case values. /// static bool CmpCaseVals(const std::pair& lhs, const std::pair& rhs) { if (lhs.first < rhs.first) return true; if (lhs.first == rhs.first && lhs.second->getCaseLoc().getRawEncoding() < rhs.second->getCaseLoc().getRawEncoding()) return true; return false; } /// CmpEnumVals - Comparison predicate for sorting enumeration values. /// static bool CmpEnumVals(const std::pair& lhs, const std::pair& rhs) { return lhs.first < rhs.first; } /// EqEnumVals - Comparison preficate for uniqing enumeration values. /// static bool EqEnumVals(const std::pair& lhs, const std::pair& rhs) { return lhs.first == rhs.first; } /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of /// potentially integral-promoted expression @p expr. static QualType GetTypeBeforeIntegralPromotion(Expr *&expr) { if (ExprWithCleanups *cleanups = dyn_cast(expr)) expr = cleanups->getSubExpr(); while (ImplicitCastExpr *impcast = dyn_cast(expr)) { if (impcast->getCastKind() != CK_IntegralCast) break; expr = impcast->getSubExpr(); } return expr->getType(); } ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) { class SwitchConvertDiagnoser : public ICEConvertDiagnoser { Expr *Cond; public: SwitchConvertDiagnoser(Expr *Cond) : ICEConvertDiagnoser(/*AllowScopedEnumerations*/true, false, true), Cond(Cond) {} SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) override { return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T; } SemaDiagnosticBuilder diagnoseIncomplete( Sema &S, SourceLocation Loc, QualType T) override { return S.Diag(Loc, diag::err_switch_incomplete_class_type) << T << Cond->getSourceRange(); } SemaDiagnosticBuilder diagnoseExplicitConv( Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override { return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy; } SemaDiagnosticBuilder noteExplicitConv( Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override { return S.Diag(Conv->getLocation(), diag::note_switch_conversion) << ConvTy->isEnumeralType() << ConvTy; } SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override { return S.Diag(Loc, diag::err_switch_multiple_conversions) << T; } SemaDiagnosticBuilder noteAmbiguous( Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override { return S.Diag(Conv->getLocation(), diag::note_switch_conversion) << ConvTy->isEnumeralType() << ConvTy; } SemaDiagnosticBuilder diagnoseConversion( Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override { llvm_unreachable("conversion functions are permitted"); } } SwitchDiagnoser(Cond); ExprResult CondResult = PerformContextualImplicitConversion(SwitchLoc, Cond, SwitchDiagnoser); if (CondResult.isInvalid()) return ExprError(); // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. return UsualUnaryConversions(CondResult.get()); } StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Stmt *InitStmt, ConditionResult Cond) { if (Cond.isInvalid()) return StmtError(); getCurFunction()->setHasBranchIntoScope(); SwitchStmt *SS = new (Context) SwitchStmt(Context, InitStmt, Cond.get().first, Cond.get().second); getCurFunction()->SwitchStack.push_back(SS); return SS; } static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) { Val = Val.extOrTrunc(BitWidth); Val.setIsSigned(IsSigned); } /// Check the specified case value is in range for the given unpromoted switch /// type. static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val, unsigned UnpromotedWidth, bool UnpromotedSign) { // If the case value was signed and negative and the switch expression is // unsigned, don't bother to warn: this is implementation-defined behavior. // FIXME: Introduce a second, default-ignored warning for this case? if (UnpromotedWidth < Val.getBitWidth()) { llvm::APSInt ConvVal(Val); AdjustAPSInt(ConvVal, UnpromotedWidth, UnpromotedSign); AdjustAPSInt(ConvVal, Val.getBitWidth(), Val.isSigned()); // FIXME: Use different diagnostics for overflow in conversion to promoted // type versus "switch expression cannot have this value". Use proper // IntRange checking rather than just looking at the unpromoted type here. if (ConvVal != Val) S.Diag(Loc, diag::warn_case_value_overflow) << Val.toString(10) << ConvVal.toString(10); } } typedef SmallVector, 64> EnumValsTy; /// Returns true if we should emit a diagnostic about this case expression not /// being a part of the enum used in the switch controlling expression. static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, const EnumDecl *ED, const Expr *CaseExpr, EnumValsTy::iterator &EI, EnumValsTy::iterator &EIEnd, const llvm::APSInt &Val) { if (const DeclRefExpr *DRE = dyn_cast(CaseExpr->IgnoreParenImpCasts())) { if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { QualType VarType = VD->getType(); QualType EnumType = S.Context.getTypeDeclType(ED); if (VD->hasGlobalStorage() && VarType.isConstQualified() && S.Context.hasSameUnqualifiedType(EnumType, VarType)) return false; } } if (ED->hasAttr()) { return !S.IsValueInFlagEnum(ED, Val, false); } else { while (EI != EIEnd && EI->first < Val) EI++; if (EI != EIEnd && EI->first == Val) return false; } return true; } StmtResult Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Stmt *BodyStmt) { SwitchStmt *SS = cast(Switch); assert(SS == getCurFunction()->SwitchStack.back() && "switch stack missing push/pop!"); getCurFunction()->SwitchStack.pop_back(); if (!BodyStmt) return StmtError(); SS->setBody(BodyStmt, SwitchLoc); Expr *CondExpr = SS->getCond(); if (!CondExpr) return StmtError(); QualType CondType = CondExpr->getType(); Expr *CondExprBeforePromotion = CondExpr; QualType CondTypeBeforePromotion = GetTypeBeforeIntegralPromotion(CondExprBeforePromotion); // C++ 6.4.2.p2: // Integral promotions are performed (on the switch condition). // // A case value unrepresentable by the original switch condition // type (before the promotion) doesn't make sense, even when it can // be represented by the promoted type. Therefore we need to find // the pre-promotion type of the switch condition. if (!CondExpr->isTypeDependent()) { // We have already converted the expression to an integral or enumeration // type, when we started the switch statement. If we don't have an // appropriate type now, just return an error. if (!CondType->isIntegralOrEnumerationType()) return StmtError(); if (CondExpr->isKnownToHaveBooleanValue()) { // switch(bool_expr) {...} is often a programmer error, e.g. // switch(n && mask) { ... } // Doh - should be "n & mask". // One can always use an if statement instead of switch(bool_expr). Diag(SwitchLoc, diag::warn_bool_switch_condition) << CondExpr->getSourceRange(); } } // Get the bitwidth of the switched-on value after promotions. We must // convert the integer case values to this width before comparison. bool HasDependentValue = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); unsigned CondWidth = HasDependentValue ? 0 : Context.getIntWidth(CondType); bool CondIsSigned = CondType->isSignedIntegerOrEnumerationType(); // Get the width and signedness that the condition might actually have, for // warning purposes. // FIXME: Grab an IntRange for the condition rather than using the unpromoted // type. unsigned CondWidthBeforePromotion = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); bool CondIsSignedBeforePromotion = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType(); // Accumulate all of the case values in a vector so that we can sort them // and detect duplicates. This vector contains the APInt for the case after // it has been converted to the condition type. typedef SmallVector, 64> CaseValsTy; CaseValsTy CaseVals; // Keep track of any GNU case ranges we see. The APSInt is the low value. typedef std::vector > CaseRangesTy; CaseRangesTy CaseRanges; DefaultStmt *TheDefaultStmt = nullptr; bool CaseListIsErroneous = false; for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue; SC = SC->getNextSwitchCase()) { if (DefaultStmt *DS = dyn_cast(SC)) { if (TheDefaultStmt) { Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined); Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev); // FIXME: Remove the default statement from the switch block so that // we'll return a valid AST. This requires recursing down the AST and // finding it, not something we are set up to do right now. For now, // just lop the entire switch stmt out of the AST. CaseListIsErroneous = true; } TheDefaultStmt = DS; } else { CaseStmt *CS = cast(SC); Expr *Lo = CS->getLHS(); if (Lo->isTypeDependent() || Lo->isValueDependent()) { HasDependentValue = true; break; } llvm::APSInt LoVal; if (getLangOpts().CPlusPlus11) { // C++11 [stmt.switch]p2: the constant-expression shall be a converted // constant expression of the promoted type of the switch condition. ExprResult ConvLo = CheckConvertedConstantExpression(Lo, CondType, LoVal, CCEK_CaseValue); if (ConvLo.isInvalid()) { CaseListIsErroneous = true; continue; } Lo = ConvLo.get(); } else { // We already verified that the expression has a i-c-e value (C99 // 6.8.4.2p3) - get that value now. LoVal = Lo->EvaluateKnownConstInt(Context); // If the LHS is not the same type as the condition, insert an implicit // cast. Lo = DefaultLvalueConversion(Lo).get(); Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).get(); } // Check the unconverted value is within the range of possible values of // the switch expression. checkCaseValue(*this, Lo->getLocStart(), LoVal, CondWidthBeforePromotion, CondIsSignedBeforePromotion); // Convert the value to the same width/sign as the condition. AdjustAPSInt(LoVal, CondWidth, CondIsSigned); CS->setLHS(Lo); // If this is a case range, remember it in CaseRanges, otherwise CaseVals. if (CS->getRHS()) { if (CS->getRHS()->isTypeDependent() || CS->getRHS()->isValueDependent()) { HasDependentValue = true; break; } CaseRanges.push_back(std::make_pair(LoVal, CS)); } else CaseVals.push_back(std::make_pair(LoVal, CS)); } } if (!HasDependentValue) { // If we don't have a default statement, check whether the // condition is constant. llvm::APSInt ConstantCondValue; bool HasConstantCond = false; if (!HasDependentValue && !TheDefaultStmt) { HasConstantCond = CondExpr->EvaluateAsInt(ConstantCondValue, Context, Expr::SE_AllowSideEffects); assert(!HasConstantCond || (ConstantCondValue.getBitWidth() == CondWidth && ConstantCondValue.isSigned() == CondIsSigned)); } bool ShouldCheckConstantCond = HasConstantCond; // Sort all the scalar case values so we can easily detect duplicates. std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals); if (!CaseVals.empty()) { for (unsigned i = 0, e = CaseVals.size(); i != e; ++i) { if (ShouldCheckConstantCond && CaseVals[i].first == ConstantCondValue) ShouldCheckConstantCond = false; if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) { // If we have a duplicate, report it. // First, determine if either case value has a name StringRef PrevString, CurrString; Expr *PrevCase = CaseVals[i-1].second->getLHS()->IgnoreParenCasts(); Expr *CurrCase = CaseVals[i].second->getLHS()->IgnoreParenCasts(); if (DeclRefExpr *DeclRef = dyn_cast(PrevCase)) { PrevString = DeclRef->getDecl()->getName(); } if (DeclRefExpr *DeclRef = dyn_cast(CurrCase)) { CurrString = DeclRef->getDecl()->getName(); } SmallString<16> CaseValStr; CaseVals[i-1].first.toString(CaseValStr); if (PrevString == CurrString) Diag(CaseVals[i].second->getLHS()->getLocStart(), diag::err_duplicate_case) << (PrevString.empty() ? StringRef(CaseValStr) : PrevString); else Diag(CaseVals[i].second->getLHS()->getLocStart(), diag::err_duplicate_case_differing_expr) << (PrevString.empty() ? StringRef(CaseValStr) : PrevString) << (CurrString.empty() ? StringRef(CaseValStr) : CurrString) << CaseValStr; Diag(CaseVals[i-1].second->getLHS()->getLocStart(), diag::note_duplicate_case_prev); // FIXME: We really want to remove the bogus case stmt from the // substmt, but we have no way to do this right now. CaseListIsErroneous = true; } } } // Detect duplicate case ranges, which usually don't exist at all in // the first place. if (!CaseRanges.empty()) { // Sort all the case ranges by their low value so we can easily detect // overlaps between ranges. std::stable_sort(CaseRanges.begin(), CaseRanges.end()); // Scan the ranges, computing the high values and removing empty ranges. std::vector HiVals; for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) { llvm::APSInt &LoVal = CaseRanges[i].first; CaseStmt *CR = CaseRanges[i].second; Expr *Hi = CR->getRHS(); llvm::APSInt HiVal; if (getLangOpts().CPlusPlus11) { // C++11 [stmt.switch]p2: the constant-expression shall be a converted // constant expression of the promoted type of the switch condition. ExprResult ConvHi = CheckConvertedConstantExpression(Hi, CondType, HiVal, CCEK_CaseValue); if (ConvHi.isInvalid()) { CaseListIsErroneous = true; continue; } Hi = ConvHi.get(); } else { HiVal = Hi->EvaluateKnownConstInt(Context); // If the RHS is not the same type as the condition, insert an // implicit cast. Hi = DefaultLvalueConversion(Hi).get(); Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).get(); } // Check the unconverted value is within the range of possible values of // the switch expression. checkCaseValue(*this, Hi->getLocStart(), HiVal, CondWidthBeforePromotion, CondIsSignedBeforePromotion); // Convert the value to the same width/sign as the condition. AdjustAPSInt(HiVal, CondWidth, CondIsSigned); CR->setRHS(Hi); // If the low value is bigger than the high value, the case is empty. if (LoVal > HiVal) { Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range) << SourceRange(CR->getLHS()->getLocStart(), Hi->getLocEnd()); CaseRanges.erase(CaseRanges.begin()+i); --i; --e; continue; } if (ShouldCheckConstantCond && LoVal <= ConstantCondValue && ConstantCondValue <= HiVal) ShouldCheckConstantCond = false; HiVals.push_back(HiVal); } // Rescan the ranges, looking for overlap with singleton values and other // ranges. Since the range list is sorted, we only need to compare case // ranges with their neighbors. for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) { llvm::APSInt &CRLo = CaseRanges[i].first; llvm::APSInt &CRHi = HiVals[i]; CaseStmt *CR = CaseRanges[i].second; // Check to see whether the case range overlaps with any // singleton cases. CaseStmt *OverlapStmt = nullptr; llvm::APSInt OverlapVal(32); // Find the smallest value >= the lower bound. If I is in the // case range, then we have overlap. CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(), CaseVals.end(), CRLo, CaseCompareFunctor()); if (I != CaseVals.end() && I->first < CRHi) { OverlapVal = I->first; // Found overlap with scalar. OverlapStmt = I->second; } // Find the smallest value bigger than the upper bound. I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor()); if (I != CaseVals.begin() && (I-1)->first >= CRLo) { OverlapVal = (I-1)->first; // Found overlap with scalar. OverlapStmt = (I-1)->second; } // Check to see if this case stmt overlaps with the subsequent // case range. if (i && CRLo <= HiVals[i-1]) { OverlapVal = HiVals[i-1]; // Found overlap with range. OverlapStmt = CaseRanges[i-1].second; } if (OverlapStmt) { // If we have a duplicate, report it. Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case) << OverlapVal.toString(10); Diag(OverlapStmt->getLHS()->getLocStart(), diag::note_duplicate_case_prev); // FIXME: We really want to remove the bogus case stmt from the // substmt, but we have no way to do this right now. CaseListIsErroneous = true; } } } // Complain if we have a constant condition and we didn't find a match. if (!CaseListIsErroneous && ShouldCheckConstantCond) { // TODO: it would be nice if we printed enums as enums, chars as // chars, etc. Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition) << ConstantCondValue.toString(10) << CondExpr->getSourceRange(); } // Check to see if switch is over an Enum and handles all of its // values. We only issue a warning if there is not 'default:', but // we still do the analysis to preserve this information in the AST // (which can be used by flow-based analyes). // const EnumType *ET = CondTypeBeforePromotion->getAs(); // If switch has default case, then ignore it. if (!CaseListIsErroneous && !HasConstantCond && ET && ET->getDecl()->isCompleteDefinition()) { const EnumDecl *ED = ET->getDecl(); EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, // allowing easier comparison with CaseVals. for (auto *EDI : ED->enumerators()) { llvm::APSInt Val = EDI->getInitVal(); AdjustAPSInt(Val, CondWidth, CondIsSigned); EnumVals.push_back(std::make_pair(Val, EDI)); } std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); auto EI = EnumVals.begin(), EIEnd = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); // See which case values aren't in enum. for (CaseValsTy::const_iterator CI = CaseVals.begin(); CI != CaseVals.end(); CI++) { Expr *CaseExpr = CI->second->getLHS(); if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, CI->first)) Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) << CondTypeBeforePromotion; } // See which of case ranges aren't in enum EI = EnumVals.begin(); for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); RI != CaseRanges.end(); RI++) { Expr *CaseExpr = RI->second->getLHS(); if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, RI->first)) Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) << CondTypeBeforePromotion; llvm::APSInt Hi = RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); CaseExpr = RI->second->getRHS(); if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd, Hi)) Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum) << CondTypeBeforePromotion; } // Check which enum vals aren't in switch auto CI = CaseVals.begin(); auto RI = CaseRanges.begin(); bool hasCasesNotInSwitch = false; SmallVector UnhandledNames; for (EI = EnumVals.begin(); EI != EIEnd; EI++){ // Drop unneeded case values while (CI != CaseVals.end() && CI->first < EI->first) CI++; if (CI != CaseVals.end() && CI->first == EI->first) continue; // Drop unneeded case ranges for (; RI != CaseRanges.end(); RI++) { llvm::APSInt Hi = RI->second->getRHS()->EvaluateKnownConstInt(Context); AdjustAPSInt(Hi, CondWidth, CondIsSigned); if (EI->first <= Hi) break; } if (RI == CaseRanges.end() || EI->first < RI->first) { hasCasesNotInSwitch = true; UnhandledNames.push_back(EI->second->getDeclName()); } } if (TheDefaultStmt && UnhandledNames.empty()) Diag(TheDefaultStmt->getDefaultLoc(), diag::warn_unreachable_default); // Produce a nice diagnostic if multiple values aren't handled. if (!UnhandledNames.empty()) { DiagnosticBuilder DB = Diag(CondExpr->getExprLoc(), TheDefaultStmt ? diag::warn_def_missing_case : diag::warn_missing_case) << (int)UnhandledNames.size(); for (size_t I = 0, E = std::min(UnhandledNames.size(), (size_t)3); I != E; ++I) DB << UnhandledNames[I]; } if (!hasCasesNotInSwitch) SS->setAllEnumCasesCovered(); } } if (BodyStmt) DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt, diag::warn_empty_switch_body); // FIXME: If the case list was broken is some way, we don't have a good system // to patch it up. Instead, just return the whole substmt as broken. if (CaseListIsErroneous) return StmtError(); return SS; } void Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, Expr *SrcExpr) { if (Diags.isIgnored(diag::warn_not_in_enum_assignment, SrcExpr->getExprLoc())) return; if (const EnumType *ET = DstType->getAs()) if (!Context.hasSameUnqualifiedType(SrcType, DstType) && SrcType->isIntegerType()) { if (!SrcExpr->isTypeDependent() && !SrcExpr->isValueDependent() && SrcExpr->isIntegerConstantExpr(Context)) { // Get the bitwidth of the enum value before promotions. unsigned DstWidth = Context.getIntWidth(DstType); bool DstIsSigned = DstType->isSignedIntegerOrEnumerationType(); llvm::APSInt RhsVal = SrcExpr->EvaluateKnownConstInt(Context); AdjustAPSInt(RhsVal, DstWidth, DstIsSigned); const EnumDecl *ED = ET->getDecl(); if (ED->hasAttr()) { if (!IsValueInFlagEnum(ED, RhsVal, true)) Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) << DstType.getUnqualifiedType(); } else { typedef SmallVector, 64> EnumValsTy; EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, // allowing easier comparison with rhs constant. for (auto *EDI : ED->enumerators()) { llvm::APSInt Val = EDI->getInitVal(); AdjustAPSInt(Val, DstWidth, DstIsSigned); EnumVals.push_back(std::make_pair(Val, EDI)); } if (EnumVals.empty()) return; std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); EnumValsTy::iterator EIend = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); // See which values aren't in the enum. EnumValsTy::const_iterator EI = EnumVals.begin(); while (EI != EIend && EI->first < RhsVal) EI++; if (EI == EIend || EI->first != RhsVal) { Diag(SrcExpr->getExprLoc(), diag::warn_not_in_enum_assignment) << DstType.getUnqualifiedType(); } } } } } StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, Stmt *Body) { if (Cond.isInvalid()) return StmtError(); auto CondVal = Cond.get(); CheckBreakContinueBinding(CondVal.second); if (CondVal.second && !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) CommaVisitor(*this).Visit(CondVal.second); DiagnoseUnusedExprResult(Body); if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); return new (Context) WhileStmt(Context, CondVal.first, CondVal.second, Body, WhileLoc); } StmtResult Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, SourceLocation WhileLoc, SourceLocation CondLParen, Expr *Cond, SourceLocation CondRParen) { assert(Cond && "ActOnDoStmt(): missing expression"); CheckBreakContinueBinding(Cond); ExprResult CondResult = CheckBooleanCondition(DoLoc, Cond); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.get(); CondResult = ActOnFinishFullExpr(Cond, DoLoc); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.get(); DiagnoseUnusedExprResult(Body); return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); } namespace { // This visitor will traverse a conditional statement and store all // the evaluated decls into a vector. Simple is set to true if none // of the excluded constructs are used. class DeclExtractor : public EvaluatedExprVisitor { llvm::SmallPtrSetImpl &Decls; SmallVectorImpl &Ranges; bool Simple; public: typedef EvaluatedExprVisitor Inherited; DeclExtractor(Sema &S, llvm::SmallPtrSetImpl &Decls, SmallVectorImpl &Ranges) : Inherited(S.Context), Decls(Decls), Ranges(Ranges), Simple(true) {} bool isSimple() { return Simple; } // Replaces the method in EvaluatedExprVisitor. void VisitMemberExpr(MemberExpr* E) { Simple = false; } // Any Stmt not whitelisted will cause the condition to be marked complex. void VisitStmt(Stmt *S) { Simple = false; } void VisitBinaryOperator(BinaryOperator *E) { Visit(E->getLHS()); Visit(E->getRHS()); } void VisitCastExpr(CastExpr *E) { Visit(E->getSubExpr()); } void VisitUnaryOperator(UnaryOperator *E) { // Skip checking conditionals with derefernces. if (E->getOpcode() == UO_Deref) Simple = false; else Visit(E->getSubExpr()); } void VisitConditionalOperator(ConditionalOperator *E) { Visit(E->getCond()); Visit(E->getTrueExpr()); Visit(E->getFalseExpr()); } void VisitParenExpr(ParenExpr *E) { Visit(E->getSubExpr()); } void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { Visit(E->getOpaqueValue()->getSourceExpr()); Visit(E->getFalseExpr()); } void VisitIntegerLiteral(IntegerLiteral *E) { } void VisitFloatingLiteral(FloatingLiteral *E) { } void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { } void VisitCharacterLiteral(CharacterLiteral *E) { } void VisitGNUNullExpr(GNUNullExpr *E) { } void VisitImaginaryLiteral(ImaginaryLiteral *E) { } void VisitDeclRefExpr(DeclRefExpr *E) { VarDecl *VD = dyn_cast(E->getDecl()); if (!VD) return; Ranges.push_back(E->getSourceRange()); Decls.insert(VD); } }; // end class DeclExtractor // DeclMatcher checks to see if the decls are used in a non-evaluated // context. class DeclMatcher : public EvaluatedExprVisitor { llvm::SmallPtrSetImpl &Decls; bool FoundDecl; public: typedef EvaluatedExprVisitor Inherited; DeclMatcher(Sema &S, llvm::SmallPtrSetImpl &Decls, Stmt *Statement) : Inherited(S.Context), Decls(Decls), FoundDecl(false) { if (!Statement) return; Visit(Statement); } void VisitReturnStmt(ReturnStmt *S) { FoundDecl = true; } void VisitBreakStmt(BreakStmt *S) { FoundDecl = true; } void VisitGotoStmt(GotoStmt *S) { FoundDecl = true; } void VisitCastExpr(CastExpr *E) { if (E->getCastKind() == CK_LValueToRValue) CheckLValueToRValueCast(E->getSubExpr()); else Visit(E->getSubExpr()); } void CheckLValueToRValueCast(Expr *E) { E = E->IgnoreParenImpCasts(); if (isa(E)) { return; } if (ConditionalOperator *CO = dyn_cast(E)) { Visit(CO->getCond()); CheckLValueToRValueCast(CO->getTrueExpr()); CheckLValueToRValueCast(CO->getFalseExpr()); return; } if (BinaryConditionalOperator *BCO = dyn_cast(E)) { CheckLValueToRValueCast(BCO->getOpaqueValue()->getSourceExpr()); CheckLValueToRValueCast(BCO->getFalseExpr()); return; } Visit(E); } void VisitDeclRefExpr(DeclRefExpr *E) { if (VarDecl *VD = dyn_cast(E->getDecl())) if (Decls.count(VD)) FoundDecl = true; } void VisitPseudoObjectExpr(PseudoObjectExpr *POE) { // Only need to visit the semantics for POE. // SyntaticForm doesn't really use the Decal. for (auto *S : POE->semantics()) { if (auto *OVE = dyn_cast(S)) // Look past the OVE into the expression it binds. Visit(OVE->getSourceExpr()); else Visit(S); } } bool FoundDeclInUse() { return FoundDecl; } }; // end class DeclMatcher void CheckForLoopConditionalStatement(Sema &S, Expr *Second, Expr *Third, Stmt *Body) { // Condition is empty if (!Second) return; if (S.Diags.isIgnored(diag::warn_variables_not_in_loop_body, Second->getLocStart())) return; PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body); llvm::SmallPtrSet Decls; SmallVector Ranges; DeclExtractor DE(S, Decls, Ranges); DE.Visit(Second); // Don't analyze complex conditionals. if (!DE.isSimple()) return; // No decls found. if (Decls.size() == 0) return; // Don't warn on volatile, static, or global variables. for (llvm::SmallPtrSetImpl::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) if ((*I)->getType().isVolatileQualified() || (*I)->hasGlobalStorage()) return; if (DeclMatcher(S, Decls, Second).FoundDeclInUse() || DeclMatcher(S, Decls, Third).FoundDeclInUse() || DeclMatcher(S, Decls, Body).FoundDeclInUse()) return; // Load decl names into diagnostic. if (Decls.size() > 4) PDiag << 0; else { PDiag << Decls.size(); for (llvm::SmallPtrSetImpl::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) PDiag << (*I)->getDeclName(); } // Load SourceRanges into diagnostic if there is room. // Otherwise, load the SourceRange of the conditional expression. if (Ranges.size() <= PartialDiagnostic::MaxArguments) for (SmallVectorImpl::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) PDiag << *I; else PDiag << Second->getSourceRange(); S.Diag(Ranges.begin()->getBegin(), PDiag); } // If Statement is an incemement or decrement, return true and sets the // variables Increment and DRE. bool ProcessIterationStmt(Sema &S, Stmt* Statement, bool &Increment, DeclRefExpr *&DRE) { if (auto Cleanups = dyn_cast(Statement)) if (!Cleanups->cleanupsHaveSideEffects()) Statement = Cleanups->getSubExpr(); if (UnaryOperator *UO = dyn_cast(Statement)) { switch (UO->getOpcode()) { default: return false; case UO_PostInc: case UO_PreInc: Increment = true; break; case UO_PostDec: case UO_PreDec: Increment = false; break; } DRE = dyn_cast(UO->getSubExpr()); return DRE; } if (CXXOperatorCallExpr *Call = dyn_cast(Statement)) { FunctionDecl *FD = Call->getDirectCallee(); if (!FD || !FD->isOverloadedOperator()) return false; switch (FD->getOverloadedOperator()) { default: return false; case OO_PlusPlus: Increment = true; break; case OO_MinusMinus: Increment = false; break; } DRE = dyn_cast(Call->getArg(0)); return DRE; } return false; } // A visitor to determine if a continue or break statement is a // subexpression. class BreakContinueFinder : public EvaluatedExprVisitor { SourceLocation BreakLoc; SourceLocation ContinueLoc; public: BreakContinueFinder(Sema &S, Stmt* Body) : Inherited(S.Context) { Visit(Body); } typedef EvaluatedExprVisitor Inherited; void VisitContinueStmt(ContinueStmt* E) { ContinueLoc = E->getContinueLoc(); } void VisitBreakStmt(BreakStmt* E) { BreakLoc = E->getBreakLoc(); } bool ContinueFound() { return ContinueLoc.isValid(); } bool BreakFound() { return BreakLoc.isValid(); } SourceLocation GetContinueLoc() { return ContinueLoc; } SourceLocation GetBreakLoc() { return BreakLoc; } }; // end class BreakContinueFinder // Emit a warning when a loop increment/decrement appears twice per loop // iteration. The conditions which trigger this warning are: // 1) The last statement in the loop body and the third expression in the // for loop are both increment or both decrement of the same variable // 2) No continue statements in the loop body. void CheckForRedundantIteration(Sema &S, Expr *Third, Stmt *Body) { // Return when there is nothing to check. if (!Body || !Third) return; if (S.Diags.isIgnored(diag::warn_redundant_loop_iteration, Third->getLocStart())) return; // Get the last statement from the loop body. CompoundStmt *CS = dyn_cast(Body); if (!CS || CS->body_empty()) return; Stmt *LastStmt = CS->body_back(); if (!LastStmt) return; bool LoopIncrement, LastIncrement; DeclRefExpr *LoopDRE, *LastDRE; if (!ProcessIterationStmt(S, Third, LoopIncrement, LoopDRE)) return; if (!ProcessIterationStmt(S, LastStmt, LastIncrement, LastDRE)) return; // Check that the two statements are both increments or both decrements // on the same variable. if (LoopIncrement != LastIncrement || LoopDRE->getDecl() != LastDRE->getDecl()) return; if (BreakContinueFinder(S, Body).ContinueFound()) return; S.Diag(LastDRE->getLocation(), diag::warn_redundant_loop_iteration) << LastDRE->getDecl() << LastIncrement; S.Diag(LoopDRE->getLocation(), diag::note_loop_iteration_here) << LoopIncrement; } } // end namespace void Sema::CheckBreakContinueBinding(Expr *E) { if (!E || getLangOpts().CPlusPlus) return; BreakContinueFinder BCFinder(*this, E); Scope *BreakParent = CurScope->getBreakParent(); if (BCFinder.BreakFound() && BreakParent) { if (BreakParent->getFlags() & Scope::SwitchScope) { Diag(BCFinder.GetBreakLoc(), diag::warn_break_binds_to_switch); } else { Diag(BCFinder.GetBreakLoc(), diag::warn_loop_ctrl_binds_to_inner) << "break"; } } else if (BCFinder.ContinueFound() && CurScope->getContinueParent()) { Diag(BCFinder.GetContinueLoc(), diag::warn_loop_ctrl_binds_to_inner) << "continue"; } } StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, Stmt *First, ConditionResult Second, FullExprArg third, SourceLocation RParenLoc, Stmt *Body) { if (Second.isInvalid()) return StmtError(); if (!getLangOpts().CPlusPlus) { if (DeclStmt *DS = dyn_cast_or_null(First)) { // C99 6.8.5p3: The declaration part of a 'for' statement shall only // declare identifiers for objects having storage class 'auto' or // 'register'. for (auto *DI : DS->decls()) { VarDecl *VD = dyn_cast(DI); if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage()) VD = nullptr; if (!VD) { Diag(DI->getLocation(), diag::err_non_local_variable_decl_in_for); DI->setInvalidDecl(); } } } } CheckBreakContinueBinding(Second.get().second); CheckBreakContinueBinding(third.get()); if (!Second.get().first) CheckForLoopConditionalStatement(*this, Second.get().second, third.get(), Body); CheckForRedundantIteration(*this, third.get(), Body); if (Second.get().second && !Diags.isIgnored(diag::warn_comma_operator, Second.get().second->getExprLoc())) CommaVisitor(*this).Visit(Second.get().second); Expr *Third = third.release().getAs(); DiagnoseUnusedExprResult(First); DiagnoseUnusedExprResult(Third); DiagnoseUnusedExprResult(Body); if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); return new (Context) ForStmt(Context, First, Second.get().second, Second.get().first, Third, Body, ForLoc, LParenLoc, RParenLoc); } /// In an Objective C collection iteration statement: /// for (x in y) /// x can be an arbitrary l-value expression. Bind it up as a /// full-expression. StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { // Reduce placeholder expressions here. Note that this rejects the // use of pseudo-object l-values in this position. ExprResult result = CheckPlaceholderExpr(E); if (result.isInvalid()) return StmtError(); E = result.get(); ExprResult FullExpr = ActOnFinishFullExpr(E); if (FullExpr.isInvalid()) return StmtError(); return StmtResult(static_cast(FullExpr.get())); } ExprResult Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { if (!collection) return ExprError(); ExprResult result = CorrectDelayedTyposInExpr(collection); if (!result.isUsable()) return ExprError(); collection = result.get(); // Bail out early if we've got a type-dependent expression. if (collection->isTypeDependent()) return collection; // Perform normal l-value conversion. result = DefaultFunctionArrayLvalueConversion(collection); if (result.isInvalid()) return ExprError(); collection = result.get(); // The operand needs to have object-pointer type. // TODO: should we do a contextual conversion? const ObjCObjectPointerType *pointerType = collection->getType()->getAs(); if (!pointerType) return Diag(forLoc, diag::err_collection_expr_type) << collection->getType() << collection->getSourceRange(); // Check that the operand provides // - countByEnumeratingWithState:objects:count: const ObjCObjectType *objectType = pointerType->getObjectType(); ObjCInterfaceDecl *iface = objectType->getInterface(); // If we have a forward-declared type, we can't do this check. // Under ARC, it is an error not to have a forward-declared class. if (iface && (getLangOpts().ObjCAutoRefCount ? RequireCompleteType(forLoc, QualType(objectType, 0), diag::err_arc_collection_forward, collection) : !isCompleteType(forLoc, QualType(objectType, 0)))) { // Otherwise, if we have any useful type information, check that // the type declares the appropriate method. } else if (iface || !objectType->qual_empty()) { IdentifierInfo *selectorIdents[] = { &Context.Idents.get("countByEnumeratingWithState"), &Context.Idents.get("objects"), &Context.Idents.get("count") }; Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]); ObjCMethodDecl *method = nullptr; // If there's an interface, look in both the public and private APIs. if (iface) { method = iface->lookupInstanceMethod(selector); if (!method) method = iface->lookupPrivateMethod(selector); } // Also check protocol qualifiers. if (!method) method = LookupMethodInQualifiedType(selector, pointerType, /*instance*/ true); // If we didn't find it anywhere, give up. if (!method) { Diag(forLoc, diag::warn_collection_expr_type) << collection->getType() << selector << collection->getSourceRange(); } // TODO: check for an incompatible signature? } // Wrap up any cleanups in the expression. return collection; } StmtResult Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, Stmt *First, Expr *collection, SourceLocation RParenLoc) { ExprResult CollectionExprResult = CheckObjCForCollectionOperand(ForLoc, collection); if (First) { QualType FirstType; if (DeclStmt *DS = dyn_cast(First)) { if (!DS->isSingleDecl()) return StmtError(Diag((*DS->decl_begin())->getLocation(), diag::err_toomany_element_decls)); VarDecl *D = dyn_cast(DS->getSingleDecl()); if (!D || D->isInvalidDecl()) return StmtError(); FirstType = D->getType(); // C99 6.8.5p3: The declaration part of a 'for' statement shall only // declare identifiers for objects having storage class 'auto' or // 'register'. if (!D->hasLocalStorage()) return StmtError(Diag(D->getLocation(), diag::err_non_local_variable_decl_in_for)); // If the type contained 'auto', deduce the 'auto' to 'id'. if (FirstType->getContainedAutoType()) { OpaqueValueExpr OpaqueId(D->getLocation(), Context.getObjCIdType(), VK_RValue); Expr *DeducedInit = &OpaqueId; if (DeduceAutoType(D->getTypeSourceInfo(), DeducedInit, FirstType) == DAR_Failed) DiagnoseAutoDeductionFailure(D, DeducedInit); if (FirstType.isNull()) { D->setInvalidDecl(); return StmtError(); } D->setType(FirstType); if (ActiveTemplateInstantiations.empty()) { SourceLocation Loc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); Diag(Loc, diag::warn_auto_var_is_id) << D->getDeclName(); } } } else { Expr *FirstE = cast(First); if (!FirstE->isTypeDependent() && !FirstE->isLValue()) return StmtError(Diag(First->getLocStart(), diag::err_selector_element_not_lvalue) << First->getSourceRange()); FirstType = static_cast(First)->getType(); if (FirstType.isConstQualified()) Diag(ForLoc, diag::err_selector_element_const_type) << FirstType << First->getSourceRange(); } if (!FirstType->isDependentType() && !FirstType->isObjCObjectPointerType() && !FirstType->isBlockPointerType()) return StmtError(Diag(ForLoc, diag::err_selector_element_type) << FirstType << First->getSourceRange()); } if (CollectionExprResult.isInvalid()) return StmtError(); CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get()); if (CollectionExprResult.isInvalid()) return StmtError(); return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(), nullptr, ForLoc, RParenLoc); } /// Finish building a variable declaration for a for-range statement. /// \return true if an error occurs. static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, SourceLocation Loc, int DiagID) { if (Decl->getType()->isUndeducedType()) { ExprResult Res = SemaRef.CorrectDelayedTyposInExpr(Init); if (!Res.isUsable()) { Decl->setInvalidDecl(); return true; } Init = Res.get(); } // Deduce the type for the iterator variable now rather than leaving it to // AddInitializerToDecl, so we can produce a more suitable diagnostic. QualType InitType; if ((!isa(Init) && Init->getType()->isVoidType()) || SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitType) == Sema::DAR_Failed) SemaRef.Diag(Loc, DiagID) << Init->getType(); if (InitType.isNull()) { Decl->setInvalidDecl(); return true; } Decl->setType(InitType); // In ARC, infer lifetime. // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if // we're doing the equivalent of fast iteration. if (SemaRef.getLangOpts().ObjCAutoRefCount && SemaRef.inferObjCARCLifetime(Decl)) Decl->setInvalidDecl(); SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false); SemaRef.FinalizeDeclaration(Decl); SemaRef.CurContext->addHiddenDecl(Decl); return false; } namespace { // An enum to represent whether something is dealing with a call to begin() // or a call to end() in a range-based for loop. enum BeginEndFunction { BEF_begin, BEF_end }; /// Produce a note indicating which begin/end function was implicitly called /// by a C++11 for-range statement. This is often not obvious from the code, /// nor from the diagnostics produced when analysing the implicit expressions /// required in a for-range statement. void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, BeginEndFunction BEF) { CallExpr *CE = dyn_cast(E); if (!CE) return; FunctionDecl *D = dyn_cast(CE->getCalleeDecl()); if (!D) return; SourceLocation Loc = D->getLocation(); std::string Description; bool IsTemplate = false; if (FunctionTemplateDecl *FunTmpl = D->getPrimaryTemplate()) { Description = SemaRef.getTemplateArgumentBindingsText( FunTmpl->getTemplateParameters(), *D->getTemplateSpecializationArgs()); IsTemplate = true; } SemaRef.Diag(Loc, diag::note_for_range_begin_end) << BEF << IsTemplate << Description << E->getType(); } /// Build a variable declaration for a for-range statement. VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, const char *Name) { DeclContext *DC = SemaRef.CurContext; IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None); Decl->setImplicit(); return Decl; } } static bool ObjCEnumerationCollection(Expr *Collection) { return !Collection->isTypeDependent() && Collection->getType()->getAs() != nullptr; } /// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement. /// /// C++11 [stmt.ranged]: /// A range-based for statement is equivalent to /// /// { /// auto && __range = range-init; /// for ( auto __begin = begin-expr, /// __end = end-expr; /// __begin != __end; /// ++__begin ) { /// for-range-declaration = *__begin; /// statement /// } /// } /// /// The body of the loop is not available yet, since it cannot be analysed until /// we have determined the type of the for-range-declaration. StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, BuildForRangeKind Kind) { if (!First) return StmtError(); if (Range && ObjCEnumerationCollection(Range)) return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); DeclStmt *DS = dyn_cast(First); assert(DS && "first part of for range not a decl stmt"); if (!DS->isSingleDecl()) { Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range); return StmtError(); } Decl *LoopVar = DS->getSingleDecl(); if (LoopVar->isInvalidDecl() || !Range || DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) { LoopVar->setInvalidDecl(); return StmtError(); } // Coroutines: 'for co_await' implicitly co_awaits its range. if (CoawaitLoc.isValid()) { ExprResult Coawait = ActOnCoawaitExpr(S, CoawaitLoc, Range); if (Coawait.isInvalid()) return StmtError(); Range = Coawait.get(); } // Build auto && __range = range-init SourceLocation RangeLoc = Range->getLocStart(); VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc, Context.getAutoRRefDeductType(), "__range"); if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc, diag::err_for_range_deduction_failure)) { LoopVar->setInvalidDecl(); return StmtError(); } // Claim the type doesn't contain auto: we've already done the checking. DeclGroupPtrTy RangeGroup = BuildDeclaratorGroup(MutableArrayRef((Decl **)&RangeVar, 1)); StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); if (RangeDecl.isInvalid()) { LoopVar->setInvalidDecl(); return StmtError(); } return BuildCXXForRangeStmt(ForLoc, CoawaitLoc, ColonLoc, RangeDecl.get(), /*BeginStmt=*/nullptr, /*EndStmt=*/nullptr, /*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind); } /// \brief Create the initialization, compare, and increment steps for /// the range-based for loop expression. /// This function does not handle array-based for loops, /// which are created in Sema::BuildCXXForRangeStmt. /// /// \returns a ForRangeStatus indicating success or what kind of error occurred. /// BeginExpr and EndExpr are set and FRS_Success is returned on success; /// CandidateSet and BEF are set and some non-success value is returned on /// failure. static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, QualType RangeType, VarDecl *BeginVar, VarDecl *EndVar, SourceLocation ColonLoc, OverloadCandidateSet *CandidateSet, ExprResult *BeginExpr, ExprResult *EndExpr, BeginEndFunction *BEF) { DeclarationNameInfo BeginNameInfo( &SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc); DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"), ColonLoc); LookupResult BeginMemberLookup(SemaRef, BeginNameInfo, Sema::LookupMemberName); LookupResult EndMemberLookup(SemaRef, EndNameInfo, Sema::LookupMemberName); if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { // - if _RangeT is a class type, the unqualified-ids begin and end are // looked up in the scope of class _RangeT as if by class member access // lookup (3.4.5), and if either (or both) finds at least one // declaration, begin-expr and end-expr are __range.begin() and // __range.end(), respectively; SemaRef.LookupQualifiedName(BeginMemberLookup, D); SemaRef.LookupQualifiedName(EndMemberLookup, D); if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { SourceLocation RangeLoc = BeginVar->getLocation(); *BEF = BeginMemberLookup.empty() ? BEF_end : BEF_begin; SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch) << RangeLoc << BeginRange->getType() << *BEF; return Sema::FRS_DiagnosticIssued; } } else { // - otherwise, begin-expr and end-expr are begin(__range) and // end(__range), respectively, where begin and end are looked up with // argument-dependent lookup (3.4.2). For the purposes of this name // lookup, namespace std is an associated namespace. } *BEF = BEF_begin; Sema::ForRangeStatus RangeStatus = SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo, BeginMemberLookup, CandidateSet, BeginRange, BeginExpr); if (RangeStatus != Sema::FRS_Success) { if (RangeStatus == Sema::FRS_DiagnosticIssued) SemaRef.Diag(BeginRange->getLocStart(), diag::note_in_for_range) << ColonLoc << BEF_begin << BeginRange->getType(); return RangeStatus; } if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF); return Sema::FRS_DiagnosticIssued; } *BEF = BEF_end; RangeStatus = SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo, EndMemberLookup, CandidateSet, EndRange, EndExpr); if (RangeStatus != Sema::FRS_Success) { if (RangeStatus == Sema::FRS_DiagnosticIssued) SemaRef.Diag(EndRange->getLocStart(), diag::note_in_for_range) << ColonLoc << BEF_end << EndRange->getType(); return RangeStatus; } if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF); return Sema::FRS_DiagnosticIssued; } return Sema::FRS_Success; } /// Speculatively attempt to dereference an invalid range expression. /// If the attempt fails, this function will return a valid, null StmtResult /// and emit no diagnostics. static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *LoopVarDecl, SourceLocation ColonLoc, Expr *Range, SourceLocation RangeLoc, SourceLocation RParenLoc) { // Determine whether we can rebuild the for-range statement with a // dereferenced range expression. ExprResult AdjustedRange; { Sema::SFINAETrap Trap(SemaRef); AdjustedRange = SemaRef.BuildUnaryOp(S, RangeLoc, UO_Deref, Range); if (AdjustedRange.isInvalid()) return StmtResult(); StmtResult SR = SemaRef.ActOnCXXForRangeStmt( S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, AdjustedRange.get(), RParenLoc, Sema::BFRK_Check); if (SR.isInvalid()) return StmtResult(); } // The attempt to dereference worked well enough that it could produce a valid // loop. Produce a fixit, and rebuild the loop with diagnostics enabled, in // case there are any other (non-fatal) problems with it. SemaRef.Diag(RangeLoc, diag::err_for_range_dereference) << Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*"); return SemaRef.ActOnCXXForRangeStmt(S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild); } namespace { /// RAII object to automatically invalidate a declaration if an error occurs. struct InvalidateOnErrorScope { InvalidateOnErrorScope(Sema &SemaRef, Decl *D, bool Enabled) : Trap(SemaRef.Diags), D(D), Enabled(Enabled) {} ~InvalidateOnErrorScope() { if (Enabled && Trap.hasErrorOccurred()) D->setInvalidDecl(); } DiagnosticErrorTrap Trap; Decl *D; bool Enabled; }; } /// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, BuildForRangeKind Kind) { // FIXME: This should not be used during template instantiation. We should // pick up the set of unqualified lookup results for the != and + operators // in the initial parse. // // Testcase (accepts-invalid): // template void f() { for (auto x : T()) {} } // namespace N { struct X { X begin(); X end(); int operator*(); }; } // bool operator!=(N::X, N::X); void operator++(N::X); // void g() { f(); } Scope *S = getCurScope(); DeclStmt *RangeDS = cast(RangeDecl); VarDecl *RangeVar = cast(RangeDS->getSingleDecl()); QualType RangeVarType = RangeVar->getType(); DeclStmt *LoopVarDS = cast(LoopVarDecl); VarDecl *LoopVar = cast(LoopVarDS->getSingleDecl()); // If we hit any errors, mark the loop variable as invalid if its type // contains 'auto'. InvalidateOnErrorScope Invalidate(*this, LoopVar, LoopVar->getType()->isUndeducedType()); StmtResult BeginDeclStmt = Begin; StmtResult EndDeclStmt = End; ExprResult NotEqExpr = Cond, IncrExpr = Inc; if (RangeVarType->isDependentType()) { // The range is implicitly used as a placeholder when it is dependent. RangeVar->markUsed(Context); // Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill // them in properly when we instantiate the loop. if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy)); } else if (!BeginDeclStmt.get()) { SourceLocation RangeLoc = RangeVar->getLocation(); const QualType RangeVarNonRefType = RangeVarType.getNonReferenceType(); ExprResult BeginRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType, VK_LValue, ColonLoc); if (BeginRangeRef.isInvalid()) return StmtError(); ExprResult EndRangeRef = BuildDeclRefExpr(RangeVar, RangeVarNonRefType, VK_LValue, ColonLoc); if (EndRangeRef.isInvalid()) return StmtError(); QualType AutoType = Context.getAutoDeductType(); Expr *Range = RangeVar->getInit(); if (!Range) return StmtError(); QualType RangeType = Range->getType(); if (RequireCompleteType(RangeLoc, RangeType, diag::err_for_range_incomplete_type)) return StmtError(); // Build auto __begin = begin-expr, __end = end-expr. VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, "__begin"); VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, "__end"); // Build begin-expr and end-expr and attach to __begin and __end variables. ExprResult BeginExpr, EndExpr; if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) { // - if _RangeT is an array type, begin-expr and end-expr are __range and // __range + __bound, respectively, where __bound is the array bound. If // _RangeT is an array of unknown size or an array of incomplete type, // the program is ill-formed; // begin-expr is __range. BeginExpr = BeginRangeRef; if (FinishForRangeVarDecl(*this, BeginVar, BeginRangeRef.get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); return StmtError(); } // Find the array bound. ExprResult BoundExpr; if (const ConstantArrayType *CAT = dyn_cast(UnqAT)) BoundExpr = IntegerLiteral::Create( Context, CAT->getSize(), Context.getPointerDiffType(), RangeLoc); else if (const VariableArrayType *VAT = dyn_cast(UnqAT)) BoundExpr = VAT->getSizeExpr(); else { // Can't be a DependentSizedArrayType or an IncompleteArrayType since // UnqAT is not incomplete and Range is not type-dependent. llvm_unreachable("Unexpected array type in for-range"); } // end-expr is __range + __bound. EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, EndRangeRef.get(), BoundExpr.get()); if (EndExpr.isInvalid()) return StmtError(); if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc, diag::err_for_range_iter_deduction_failure)) { NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); return StmtError(); } } else { OverloadCandidateSet CandidateSet(RangeLoc, OverloadCandidateSet::CSK_Normal); BeginEndFunction BEFFailure; ForRangeStatus RangeStatus = BuildNonArrayForRange(*this, BeginRangeRef.get(), EndRangeRef.get(), RangeType, BeginVar, EndVar, ColonLoc, &CandidateSet, &BeginExpr, &EndExpr, &BEFFailure); if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction && BEFFailure == BEF_begin) { // If the range is being built from an array parameter, emit a // a diagnostic that it is being treated as a pointer. if (DeclRefExpr *DRE = dyn_cast(Range)) { if (ParmVarDecl *PVD = dyn_cast(DRE->getDecl())) { QualType ArrayTy = PVD->getOriginalType(); QualType PointerTy = PVD->getType(); if (PointerTy->isPointerType() && ArrayTy->isArrayType()) { Diag(Range->getLocStart(), diag::err_range_on_array_parameter) << RangeLoc << PVD << ArrayTy << PointerTy; Diag(PVD->getLocation(), diag::note_declared_at); return StmtError(); } } } // If building the range failed, try dereferencing the range expression // unless a diagnostic was issued or the end function is problematic. StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc, CoawaitLoc, LoopVarDecl, ColonLoc, Range, RangeLoc, RParenLoc); if (SR.isInvalid() || SR.isUsable()) return SR; } // Otherwise, emit diagnostics if we haven't already. if (RangeStatus == FRS_NoViableFunction) { Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get(); Diag(Range->getLocStart(), diag::err_for_range_invalid) << RangeLoc << Range->getType() << BEFFailure; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Range); } // Return an error if no fix was discovered. if (RangeStatus != FRS_Success) return StmtError(); } assert(!BeginExpr.isInvalid() && !EndExpr.isInvalid() && "invalid range expression in for loop"); // C++11 [dcl.spec.auto]p7: BeginType and EndType must be the same. // C++1z removes this restriction. QualType BeginType = BeginVar->getType(), EndType = EndVar->getType(); if (!Context.hasSameType(BeginType, EndType)) { Diag(RangeLoc, getLangOpts().CPlusPlus1z ? diag::warn_for_range_begin_end_types_differ : diag::ext_for_range_begin_end_types_differ) << BeginType << EndType; NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); } BeginDeclStmt = ActOnDeclStmt(ConvertDeclToDeclGroup(BeginVar), ColonLoc, ColonLoc); EndDeclStmt = ActOnDeclStmt(ConvertDeclToDeclGroup(EndVar), ColonLoc, ColonLoc); const QualType BeginRefNonRefType = BeginType.getNonReferenceType(); ExprResult BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, VK_LValue, ColonLoc); if (BeginRef.isInvalid()) return StmtError(); ExprResult EndRef = BuildDeclRefExpr(EndVar, EndType.getNonReferenceType(), VK_LValue, ColonLoc); if (EndRef.isInvalid()) return StmtError(); // Build and check __begin != __end expression. NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal, BeginRef.get(), EndRef.get()); if (!NotEqExpr.isInvalid()) NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get()); if (!NotEqExpr.isInvalid()) NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); if (NotEqExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 0 << BeginRangeRef.get()->getType(); NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); if (!Context.hasSameType(BeginType, EndType)) NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); return StmtError(); } // Build and check ++__begin expression. BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, VK_LValue, ColonLoc); if (BeginRef.isInvalid()) return StmtError(); IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); if (!IncrExpr.isInvalid() && CoawaitLoc.isValid()) IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); if (!IncrExpr.isInvalid()) IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); if (IncrExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 2 << BeginRangeRef.get()->getType() ; NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); return StmtError(); } // Build and check *__begin expression. BeginRef = BuildDeclRefExpr(BeginVar, BeginRefNonRefType, VK_LValue, ColonLoc); if (BeginRef.isInvalid()) return StmtError(); ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get()); if (DerefExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 1 << BeginRangeRef.get()->getType(); NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); return StmtError(); } // Attach *__begin as initializer for VD. Don't touch it if we're just // trying to determine whether this would be a valid range. if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) { AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false); if (LoopVar->isInvalidDecl()) NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); } } // Don't bother to actually allocate the result if we're just trying to // determine whether it would be valid. if (Kind == BFRK_Check) return StmtResult(); return new (Context) CXXForRangeStmt( RangeDS, cast_or_null(BeginDeclStmt.get()), cast_or_null(EndDeclStmt.get()), NotEqExpr.get(), IncrExpr.get(), LoopVarDS, /*Body=*/nullptr, ForLoc, CoawaitLoc, ColonLoc, RParenLoc); } /// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach /// statement. StmtResult Sema::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); ObjCForCollectionStmt * ForStmt = cast(S); ForStmt->setBody(B); return S; } // Warn when the loop variable is a const reference that creates a copy. // Suggest using the non-reference type for copies. If a copy can be prevented // suggest the const reference type that would do so. // For instance, given "for (const &Foo : Range)", suggest // "for (const Foo : Range)" to denote a copy is made for the loop. If // possible, also suggest "for (const &Bar : Range)" if this type prevents // the copy altogether. static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, const VarDecl *VD, QualType RangeInitType) { const Expr *InitExpr = VD->getInit(); if (!InitExpr) return; QualType VariableType = VD->getType(); if (auto Cleanups = dyn_cast(InitExpr)) if (!Cleanups->cleanupsHaveSideEffects()) InitExpr = Cleanups->getSubExpr(); const MaterializeTemporaryExpr *MTE = dyn_cast(InitExpr); // No copy made. if (!MTE) return; const Expr *E = MTE->GetTemporaryExpr()->IgnoreImpCasts(); // Searching for either UnaryOperator for dereference of a pointer or // CXXOperatorCallExpr for handling iterators. while (!isa(E) && !isa(E)) { if (const CXXConstructExpr *CCE = dyn_cast(E)) { E = CCE->getArg(0); } else if (const CXXMemberCallExpr *Call = dyn_cast(E)) { const MemberExpr *ME = cast(Call->getCallee()); E = ME->getBase(); } else { const MaterializeTemporaryExpr *MTE = cast(E); E = MTE->GetTemporaryExpr(); } E = E->IgnoreImpCasts(); } bool ReturnsReference = false; if (isa(E)) { ReturnsReference = true; } else { const CXXOperatorCallExpr *Call = cast(E); const FunctionDecl *FD = Call->getDirectCallee(); QualType ReturnType = FD->getReturnType(); ReturnsReference = ReturnType->isReferenceType(); } if (ReturnsReference) { // Loop variable creates a temporary. Suggest either to go with // non-reference loop variable to indiciate a copy is made, or // the correct time to bind a const reference. SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy) << VD << VariableType << E->getType(); QualType NonReferenceType = VariableType.getNonReferenceType(); NonReferenceType.removeLocalConst(); QualType NewReferenceType = SemaRef.Context.getLValueReferenceType(E->getType().withConst()); SemaRef.Diag(VD->getLocStart(), diag::note_use_type_or_non_reference) << NonReferenceType << NewReferenceType << VD->getSourceRange(); } else { // The range always returns a copy, so a temporary is always created. // Suggest removing the reference from the loop variable. SemaRef.Diag(VD->getLocation(), diag::warn_for_range_variable_always_copy) << VD << RangeInitType; QualType NonReferenceType = VariableType.getNonReferenceType(); NonReferenceType.removeLocalConst(); SemaRef.Diag(VD->getLocStart(), diag::note_use_non_reference_type) << NonReferenceType << VD->getSourceRange(); } } // Warns when the loop variable can be changed to a reference type to // prevent a copy. For instance, if given "for (const Foo x : Range)" suggest // "for (const Foo &x : Range)" if this form does not make a copy. static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef, const VarDecl *VD) { const Expr *InitExpr = VD->getInit(); if (!InitExpr) return; QualType VariableType = VD->getType(); if (const CXXConstructExpr *CE = dyn_cast(InitExpr)) { if (!CE->getConstructor()->isCopyConstructor()) return; } else if (const CastExpr *CE = dyn_cast(InitExpr)) { if (CE->getCastKind() != CK_LValueToRValue) return; } else { return; } // TODO: Determine a maximum size that a POD type can be before a diagnostic // should be emitted. Also, only ignore POD types with trivial copy // constructors. if (VariableType.isPODType(SemaRef.Context)) return; // Suggest changing from a const variable to a const reference variable // if doing so will prevent a copy. SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy) << VD << VariableType << InitExpr->getType(); SemaRef.Diag(VD->getLocStart(), diag::note_use_reference_type) << SemaRef.Context.getLValueReferenceType(VariableType) << VD->getSourceRange(); } /// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them. /// 1) for (const foo &x : foos) where foos only returns a copy. Suggest /// using "const foo x" to show that a copy is made /// 2) for (const bar &x : foos) where bar is a temporary intialized by bar. /// Suggest either "const bar x" to keep the copying or "const foo& x" to /// prevent the copy. /// 3) for (const foo x : foos) where x is constructed from a reference foo. /// Suggest "const foo &x" to prevent the copy. static void DiagnoseForRangeVariableCopies(Sema &SemaRef, const CXXForRangeStmt *ForStmt) { if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy, ForStmt->getLocStart()) && SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy, ForStmt->getLocStart()) && SemaRef.Diags.isIgnored(diag::warn_for_range_copy, ForStmt->getLocStart())) { return; } const VarDecl *VD = ForStmt->getLoopVariable(); if (!VD) return; QualType VariableType = VD->getType(); if (VariableType->isIncompleteType()) return; const Expr *InitExpr = VD->getInit(); if (!InitExpr) return; if (VariableType->isReferenceType()) { DiagnoseForRangeReferenceVariableCopies(SemaRef, VD, ForStmt->getRangeInit()->getType()); } else if (VariableType.isConstQualified()) { DiagnoseForRangeConstVariableCopies(SemaRef, VD); } } /// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. /// This is a separate step from ActOnCXXForRangeStmt because analysis of the /// body cannot be performed until after the type of the range variable is /// determined. StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); if (isa(S)) return FinishObjCForCollectionStmt(S, B); CXXForRangeStmt *ForStmt = cast(S); ForStmt->setBody(B); DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B, diag::warn_empty_range_based_for_body); DiagnoseForRangeVariableCopies(*this, ForStmt); return S; } StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl) { getCurFunction()->setHasBranchIntoScope(); TheDecl->markUsed(Context); return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc); } StmtResult Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, Expr *E) { // Convert operand to void* if (!E->isTypeDependent()) { QualType ETy = E->getType(); QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); ExprResult ExprRes = E; AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DestTy, ExprRes); if (ExprRes.isInvalid()) return StmtError(); E = ExprRes.get(); if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); } ExprResult ExprRes = ActOnFinishFullExpr(E); if (ExprRes.isInvalid()) return StmtError(); E = ExprRes.get(); getCurFunction()->setHasIndirectGoto(); return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E); } static void CheckJumpOutOfSEHFinally(Sema &S, SourceLocation Loc, const Scope &DestScope) { if (!S.CurrentSEHFinally.empty() && DestScope.Contains(*S.CurrentSEHFinally.back())) { S.Diag(Loc, diag::warn_jump_out_of_seh_finally); } } StmtResult Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { Scope *S = CurScope->getContinueParent(); if (!S) { // C99 6.8.6.2p1: A break shall appear only in or as a loop body. return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop)); } CheckJumpOutOfSEHFinally(*this, ContinueLoc, *S); return new (Context) ContinueStmt(ContinueLoc); } StmtResult Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { Scope *S = CurScope->getBreakParent(); if (!S) { // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body. return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch)); } if (S->isOpenMPLoopScope()) return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt) << "break"); CheckJumpOutOfSEHFinally(*this, BreakLoc, *S); return new (Context) BreakStmt(BreakLoc); } /// \brief Determine whether the given expression is a candidate for /// copy elision in either a return statement or a throw expression. /// /// \param ReturnType If we're determining the copy elision candidate for /// a return statement, this is the return type of the function. If we're /// determining the copy elision candidate for a throw expression, this will /// be a NULL type. /// /// \param E The expression being returned from the function or block, or /// being thrown. /// /// \param AllowParamOrMoveConstructible Whether we allow function parameters or /// id-expressions that could be moved out of the function to be considered NRVO /// candidates. C++ prohibits these for NRVO itself, but we re-use this logic to /// determine whether we should try to move as part of a return or throw (which /// does allow function parameters). /// /// \returns The NRVO candidate variable, if the return statement may use the /// NRVO, or NULL if there is no such candidate. VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E, bool AllowParamOrMoveConstructible) { if (!getLangOpts().CPlusPlus) return nullptr; // - in a return statement in a function [where] ... // ... the expression is the name of a non-volatile automatic object ... DeclRefExpr *DR = dyn_cast(E->IgnoreParens()); if (!DR || DR->refersToEnclosingVariableOrCapture()) return nullptr; VarDecl *VD = dyn_cast(DR->getDecl()); if (!VD) return nullptr; if (isCopyElisionCandidate(ReturnType, VD, AllowParamOrMoveConstructible)) return VD; return nullptr; } bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, bool AllowParamOrMoveConstructible) { QualType VDType = VD->getType(); // - in a return statement in a function with ... // ... a class return type ... if (!ReturnType.isNull() && !ReturnType->isDependentType()) { if (!ReturnType->isRecordType()) return false; // ... the same cv-unqualified type as the function return type ... // When considering moving this expression out, allow dissimilar types. if (!AllowParamOrMoveConstructible && !VDType->isDependentType() && !Context.hasSameUnqualifiedType(ReturnType, VDType)) return false; } // ...object (other than a function or catch-clause parameter)... if (VD->getKind() != Decl::Var && !(AllowParamOrMoveConstructible && VD->getKind() == Decl::ParmVar)) return false; if (VD->isExceptionVariable()) return false; // ...automatic... if (!VD->hasLocalStorage()) return false; + // Return false if VD is a __block variable. We don't want to implicitly move + // out of a __block variable during a return because we cannot assume the + // variable will no longer be used. + if (VD->hasAttr()) return false; + if (AllowParamOrMoveConstructible) return true; // ...non-volatile... if (VD->getType().isVolatileQualified()) return false; - - // __block variables can't be allocated in a way that permits NRVO. - if (VD->hasAttr()) return false; // Variables with higher required alignment than their type's ABI // alignment cannot use NRVO. if (!VD->getType()->isDependentType() && VD->hasAttr() && Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType())) return false; return true; } /// \brief Perform the initialization of a potentially-movable value, which /// is the result of return value. /// /// This routine implements C++14 [class.copy]p32, which attempts to treat /// returned lvalues as rvalues in certain cases (to prefer move construction), /// then falls back to treating them as lvalues if that failed. ExprResult Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, const VarDecl *NRVOCandidate, QualType ResultType, Expr *Value, bool AllowNRVO) { // C++14 [class.copy]p32: // When the criteria for elision of a copy/move operation are met, but not for // an exception-declaration, and the object to be copied is designated by an // lvalue, or when the expression in a return statement is a (possibly // parenthesized) id-expression that names an object with automatic storage // duration declared in the body or parameter-declaration-clause of the // innermost enclosing function or lambda-expression, overload resolution to // select the constructor for the copy is first performed as if the object // were designated by an rvalue. ExprResult Res = ExprError(); if (AllowNRVO && !NRVOCandidate) NRVOCandidate = getCopyElisionCandidate(ResultType, Value, true); if (AllowNRVO && NRVOCandidate) { ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(), CK_NoOp, Value, VK_XValue); Expr *InitExpr = &AsRvalue; InitializationKind Kind = InitializationKind::CreateCopy( Value->getLocStart(), Value->getLocStart()); InitializationSequence Seq(*this, Entity, Kind, InitExpr); if (Seq) { for (const InitializationSequence::Step &Step : Seq.steps()) { if (!(Step.Kind == InitializationSequence::SK_ConstructorInitialization || (Step.Kind == InitializationSequence::SK_UserConversion && isa(Step.Function.Function)))) continue; CXXConstructorDecl *Constructor = cast(Step.Function.Function); const RValueReferenceType *RRefType = Constructor->getParamDecl(0)->getType() ->getAs(); // [...] If the first overload resolution fails or was not performed, or // if the type of the first parameter of the selected constructor is not // an rvalue reference to the object’s type (possibly cv-qualified), // overload resolution is performed again, considering the object as an // lvalue. if (!RRefType || !Context.hasSameUnqualifiedType(RRefType->getPointeeType(), NRVOCandidate->getType())) break; // Promote "AsRvalue" to the heap, since we now need this // expression node to persist. Value = ImplicitCastExpr::Create(Context, Value->getType(), CK_NoOp, Value, nullptr, VK_XValue); // Complete type-checking the initialization of the return type // using the constructor we found. Res = Seq.Perform(*this, Entity, Kind, Value); } } } // Either we didn't meet the criteria for treating an lvalue as an rvalue, // above, or overload resolution failed. Either way, we need to try // (again) now with the return value expression as written. if (Res.isInvalid()) Res = PerformCopyInitialization(Entity, SourceLocation(), Value); return Res; } /// \brief Determine whether the declared return type of the specified function /// contains 'auto'. static bool hasDeducedReturnType(FunctionDecl *FD) { const FunctionProtoType *FPT = FD->getTypeSourceInfo()->getType()->castAs(); return FPT->getReturnType()->isUndeducedType(); } /// ActOnCapScopeReturnStmt - Utility routine to type-check return statements /// for capturing scopes. /// StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If this is the first return we've seen, infer the return type. // [expr.prim.lambda]p4 in C++11; block literals follow the same rules. CapturingScopeInfo *CurCap = cast(getCurFunction()); QualType FnRetType = CurCap->ReturnType; LambdaScopeInfo *CurLambda = dyn_cast(CurCap); bool HasDeducedReturnType = CurLambda && hasDeducedReturnType(CurLambda->CallOperator); if (ExprEvalContexts.back().Context == DiscardedStatement && (HasDeducedReturnType || CurCap->HasImplicitReturnType)) { if (RetValExp) { ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } return new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); } if (HasDeducedReturnType) { // In C++1y, the return type may involve 'auto'. // FIXME: Blocks might have a return type of 'auto' explicitly specified. FunctionDecl *FD = CurLambda->CallOperator; if (CurCap->ReturnType.isNull()) CurCap->ReturnType = FD->getReturnType(); AutoType *AT = CurCap->ReturnType->getContainedAutoType(); assert(AT && "lost auto type from lambda return type"); if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); return StmtError(); } CurCap->ReturnType = FnRetType = FD->getReturnType(); } else if (CurCap->HasImplicitReturnType) { // For blocks/lambdas with implicit return types, we check each return // statement individually, and deduce the common return type when the block // or lambda is completed. // FIXME: Fold this into the 'auto' codepath above. if (RetValExp && !isa(RetValExp)) { ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); if (Result.isInvalid()) return StmtError(); RetValExp = Result.get(); // DR1048: even prior to C++14, we should use the 'auto' deduction rules // when deducing a return type for a lambda-expression (or by extension // for a block). These rules differ from the stated C++11 rules only in // that they remove top-level cv-qualifiers. if (!CurContext->isDependentContext()) FnRetType = RetValExp->getType().getUnqualifiedType(); else FnRetType = CurCap->ReturnType = Context.DependentTy; } else { if (RetValExp) { // C++11 [expr.lambda.prim]p4 bans inferring the result from an // initializer list, because it is not an expression (even // though we represent it as one). We still deduce 'void'. Diag(ReturnLoc, diag::err_lambda_return_init_list) << RetValExp->getSourceRange(); } FnRetType = Context.VoidTy; } // Although we'll properly infer the type of the block once it's completed, // make sure we provide a return type now for better error recovery. if (CurCap->ReturnType.isNull()) CurCap->ReturnType = FnRetType; } assert(!FnRetType.isNull()); if (BlockScopeInfo *CurBlock = dyn_cast(CurCap)) { if (CurBlock->FunctionType->getAs()->getNoReturnAttr()) { Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr); return StmtError(); } } else if (CapturedRegionScopeInfo *CurRegion = dyn_cast(CurCap)) { Diag(ReturnLoc, diag::err_return_in_captured_stmt) << CurRegion->getRegionName(); return StmtError(); } else { assert(CurLambda && "unknown kind of captured scope"); if (CurLambda->CallOperator->getType()->getAs() ->getNoReturnAttr()) { Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr); return StmtError(); } } // Otherwise, verify that this result type matches the previous one. We are // pickier with blocks than for normal functions because we don't have GCC // compatibility to worry about here. const VarDecl *NRVOCandidate = nullptr; if (FnRetType->isDependentType()) { // Delay processing for now. TODO: there are lots of dependent // types we can conclusively prove aren't void. } else if (FnRetType->isVoidType()) { if (RetValExp && !isa(RetValExp) && !(getLangOpts().CPlusPlus && (RetValExp->isTypeDependent() || RetValExp->getType()->isVoidType()))) { if (!getLangOpts().CPlusPlus && RetValExp->getType()->isVoidType()) Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2; else { Diag(ReturnLoc, diag::err_return_block_has_expr); RetValExp = nullptr; } } } else if (!RetValExp) { return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); } else if (!RetValExp->isTypeDependent()) { // we have a non-void block with an expression, continue checking // C99 6.8.6.4p3(136): The return statement is not an assignment. The // overlap restriction of subclause 6.5.16.1 does not apply to the case of // function return. // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, FnRetType, NRVOCandidate != nullptr); ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, FnRetType, RetValExp); if (Res.isInvalid()) { // FIXME: Cleanup temporaries here, anyway? return StmtError(); } RetValExp = Res.get(); CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc); } else { NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); } if (RetValExp) { ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); // If we need to check for the named return value optimization, // or if we need to infer the return type, // save the return statement in our scope for later processing. if (CurCap->HasImplicitReturnType || NRVOCandidate) FunctionScopes.back()->Returns.push_back(Result); if (FunctionScopes.back()->FirstReturnLoc.isInvalid()) FunctionScopes.back()->FirstReturnLoc = ReturnLoc; return Result; } namespace { /// \brief Marks all typedefs in all local classes in a type referenced. /// /// In a function like /// auto f() { /// struct S { typedef int a; }; /// return S(); /// } /// /// the local type escapes and could be referenced in some TUs but not in /// others. Pretend that all local typedefs are always referenced, to not warn /// on this. This isn't necessary if f has internal linkage, or the typedef /// is private. class LocalTypedefNameReferencer : public RecursiveASTVisitor { public: LocalTypedefNameReferencer(Sema &S) : S(S) {} bool VisitRecordType(const RecordType *RT); private: Sema &S; }; bool LocalTypedefNameReferencer::VisitRecordType(const RecordType *RT) { auto *R = dyn_cast(RT->getDecl()); if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() || R->isDependentType()) return true; for (auto *TmpD : R->decls()) if (auto *T = dyn_cast(TmpD)) if (T->getAccess() != AS_private || R->hasFriends()) S.MarkAnyDeclReferenced(T->getLocation(), T, /*OdrUse=*/false); return true; } } TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const { TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); while (auto ATL = TL.getAs()) TL = ATL.getModifiedLoc().IgnoreParens(); return TL.castAs().getReturnLoc(); } /// Deduce the return type for a function from a returned expression, per /// C++1y [dcl.spec.auto]p6. bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, Expr *&RetExpr, AutoType *AT) { TypeLoc OrigResultType = getReturnTypeLoc(FD); QualType Deduced; if (RetExpr && isa(RetExpr)) { // If the deduction is for a return statement and the initializer is // a braced-init-list, the program is ill-formed. Diag(RetExpr->getExprLoc(), getCurLambda() ? diag::err_lambda_return_init_list : diag::err_auto_fn_return_init_list) << RetExpr->getSourceRange(); return true; } if (FD->isDependentContext()) { // C++1y [dcl.spec.auto]p12: // Return type deduction [...] occurs when the definition is // instantiated even if the function body contains a return // statement with a non-type-dependent operand. assert(AT->isDeduced() && "should have deduced to dependent type"); return false; } if (RetExpr) { // Otherwise, [...] deduce a value for U using the rules of template // argument deduction. DeduceAutoResult DAR = DeduceAutoType(OrigResultType, RetExpr, Deduced); if (DAR == DAR_Failed && !FD->isInvalidDecl()) Diag(RetExpr->getExprLoc(), diag::err_auto_fn_deduction_failure) << OrigResultType.getType() << RetExpr->getType(); if (DAR != DAR_Succeeded) return true; // If a local type is part of the returned type, mark its fields as // referenced. LocalTypedefNameReferencer Referencer(*this); Referencer.TraverseType(RetExpr->getType()); } else { // In the case of a return with no operand, the initializer is considered // to be void(). // // Deduction here can only succeed if the return type is exactly 'cv auto' // or 'decltype(auto)', so just check for that case directly. if (!OrigResultType.getType()->getAs()) { Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto) << OrigResultType.getType(); return true; } // We always deduce U = void in this case. Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy); if (Deduced.isNull()) return true; } // If a function with a declared return type that contains a placeholder type // has multiple return statements, the return type is deduced for each return // statement. [...] if the type deduced is not the same in each deduction, // the program is ill-formed. QualType DeducedT = AT->getDeducedType(); if (!DeducedT.isNull() && !FD->isInvalidDecl()) { AutoType *NewAT = Deduced->getContainedAutoType(); // It is possible that NewAT->getDeducedType() is null. When that happens, // we should not crash, instead we ignore this deduction. if (NewAT->getDeducedType().isNull()) return false; CanQualType OldDeducedType = Context.getCanonicalFunctionResultType( DeducedT); CanQualType NewDeducedType = Context.getCanonicalFunctionResultType( NewAT->getDeducedType()); if (!FD->isDependentContext() && OldDeducedType != NewDeducedType) { const LambdaScopeInfo *LambdaSI = getCurLambda(); if (LambdaSI && LambdaSI->HasImplicitReturnType) { Diag(ReturnLoc, diag::err_typecheck_missing_return_type_incompatible) << NewAT->getDeducedType() << DeducedT << true /*IsLambda*/; } else { Diag(ReturnLoc, diag::err_auto_fn_different_deductions) << (AT->isDecltypeAuto() ? 1 : 0) << NewAT->getDeducedType() << DeducedT; } return true; } } else if (!FD->isInvalidDecl()) { // Update all declarations of the function to have the deduced return type. Context.adjustDeducedFunctionResultType(FD, Deduced); } return false; } StmtResult Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, Scope *CurScope) { StmtResult R = BuildReturnStmt(ReturnLoc, RetValExp); if (R.isInvalid() || ExprEvalContexts.back().Context == DiscardedStatement) return R; if (VarDecl *VD = const_cast(cast(R.get())->getNRVOCandidate())) { CurScope->addNRVOCandidate(VD); } else { CurScope->setNoNRVO(); } CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent()); return R; } StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // Check for unexpanded parameter packs. if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); if (isa(getCurFunction())) return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp); QualType FnRetType; QualType RelatedRetType; const AttrVec *Attrs = nullptr; bool isObjCMethod = false; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getReturnType(); if (FD->hasAttrs()) Attrs = &FD->getAttrs(); if (FD->isNoReturn()) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD->getDeclName(); if (FD->isMain() && RetValExp) if (isa(RetValExp)) Diag(ReturnLoc, diag::warn_main_returns_bool_literal) << RetValExp->getSourceRange(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { FnRetType = MD->getReturnType(); isObjCMethod = true; if (MD->hasAttrs()) Attrs = &MD->getAttrs(); if (MD->hasRelatedResultType() && MD->getClassInterface()) { // In the implementation of a method with a related return type, the // type used to type-check the validity of return statements within the // method body is a pointer to the type of the class being implemented. RelatedRetType = Context.getObjCInterfaceType(MD->getClassInterface()); RelatedRetType = Context.getObjCObjectPointerType(RelatedRetType); } } else // If we don't have a function/method context, bail. return StmtError(); // C++1z: discarded return statements are not considered when deducing a // return type. if (ExprEvalContexts.back().Context == DiscardedStatement && FnRetType->getContainedAutoType()) { if (RetValExp) { ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } return new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); } // FIXME: Add a flag to the ScopeInfo to indicate whether we're performing // deduction. if (getLangOpts().CPlusPlus14) { if (AutoType *AT = FnRetType->getContainedAutoType()) { FunctionDecl *FD = cast(CurContext); if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); return StmtError(); } else { FnRetType = FD->getReturnType(); } } } bool HasDependentReturnType = FnRetType->isDependentType(); ReturnStmt *Result = nullptr; if (FnRetType->isVoidType()) { if (RetValExp) { if (isa(RetValExp)) { // We simply never allow init lists as the return value of void // functions. This is compatible because this was never allowed before, // so there's no legacy code to deal with. NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); int FunctionKind = 0; if (isa(CurDecl)) FunctionKind = 1; else if (isa(CurDecl)) FunctionKind = 2; else if (isa(CurDecl)) FunctionKind = 3; Diag(ReturnLoc, diag::err_return_init_list) << CurDecl->getDeclName() << FunctionKind << RetValExp->getSourceRange(); // Drop the expression. RetValExp = nullptr; } else if (!RetValExp->isTypeDependent()) { // C99 6.8.6.4p1 (ext_ since GCC warns) unsigned D = diag::ext_return_has_expr; if (RetValExp->getType()->isVoidType()) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); if (isa(CurDecl) || isa(CurDecl)) D = diag::err_ctor_dtor_returns_void; else D = diag::ext_return_has_void_expr; } else { ExprResult Result = RetValExp; Result = IgnoredValueConversions(Result.get()); if (Result.isInvalid()) return StmtError(); RetValExp = Result.get(); RetValExp = ImpCastExprToType(RetValExp, Context.VoidTy, CK_ToVoid).get(); } // return of void in constructor/destructor is illegal in C++. if (D == diag::err_ctor_dtor_returns_void) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); Diag(ReturnLoc, D) << CurDecl->getDeclName() << isa(CurDecl) << RetValExp->getSourceRange(); } // return (some void expression); is legal in C++. else if (D != diag::ext_return_has_void_expr || !getLangOpts().CPlusPlus) { NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); int FunctionKind = 0; if (isa(CurDecl)) FunctionKind = 1; else if (isa(CurDecl)) FunctionKind = 2; else if (isa(CurDecl)) FunctionKind = 3; Diag(ReturnLoc, D) << CurDecl->getDeclName() << FunctionKind << RetValExp->getSourceRange(); } } if (RetValExp) { ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } } Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); } else if (!RetValExp && !HasDependentReturnType) { FunctionDecl *FD = getCurFunctionDecl(); unsigned DiagID; if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { // C++11 [stmt.return]p2 DiagID = diag::err_constexpr_return_missing_expr; FD->setInvalidDecl(); } else if (getLangOpts().C99) { // C99 6.8.6.4p1 (ext_ since GCC warns) DiagID = diag::ext_return_missing_expr; } else { // C90 6.6.6.4p4 DiagID = diag::warn_return_missing_expr; } if (FD) Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/; else Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; Result = new (Context) ReturnStmt(ReturnLoc); } else { assert(RetValExp || HasDependentReturnType); const VarDecl *NRVOCandidate = nullptr; QualType RetType = RelatedRetType.isNull() ? FnRetType : RelatedRetType; // C99 6.8.6.4p3(136): The return statement is not an assignment. The // overlap restriction of subclause 6.5.16.1 does not apply to the case of // function return. // In C++ the return statement is handled via a copy initialization, // the C version of which boils down to CheckSingleAssignmentConstraints. if (RetValExp) NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); if (!HasDependentReturnType && !RetValExp->isTypeDependent()) { // we have a non-void function with an expression, continue checking InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, RetType, NRVOCandidate != nullptr); ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, RetType, RetValExp); if (Res.isInvalid()) { // FIXME: Clean up temporaries here anyway? return StmtError(); } RetValExp = Res.getAs(); // If we have a related result type, we need to implicitly // convert back to the formal result type. We can't pretend to // initialize the result again --- we might end double-retaining // --- so instead we initialize a notional temporary. if (!RelatedRetType.isNull()) { Entity = InitializedEntity::InitializeRelatedResult(getCurMethodDecl(), FnRetType); Res = PerformCopyInitialization(Entity, ReturnLoc, RetValExp); if (Res.isInvalid()) { // FIXME: Clean up temporaries here anyway? return StmtError(); } RetValExp = Res.getAs(); } CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc, isObjCMethod, Attrs, getCurFunctionDecl()); } if (RetValExp) { ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); } Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); } // If we need to check for the named return value optimization, save the // return statement in our scope for later processing. if (Result->getNRVOCandidate()) FunctionScopes.back()->Returns.push_back(Result); if (FunctionScopes.back()->FirstReturnLoc.isInvalid()) FunctionScopes.back()->FirstReturnLoc = ReturnLoc; return Result; } StmtResult Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, Decl *Parm, Stmt *Body) { VarDecl *Var = cast_or_null(Parm); if (Var && Var->isInvalidDecl()) return StmtError(); return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body); } StmtResult Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { return new (Context) ObjCAtFinallyStmt(AtLoc, Body); } StmtResult Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, MultiStmtArg CatchStmts, Stmt *Finally) { if (!getLangOpts().ObjCExceptions) Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; getCurFunction()->setHasBranchProtectedScope(); unsigned NumCatchStmts = CatchStmts.size(); return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(), NumCatchStmts, Finally); } StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Throw) { ExprResult Result = DefaultLvalueConversion(Throw); if (Result.isInvalid()) return StmtError(); Result = ActOnFinishFullExpr(Result.get()); if (Result.isInvalid()) return StmtError(); Throw = Result.get(); QualType ThrowType = Throw->getType(); // Make sure the expression type is an ObjC pointer or "void *". if (!ThrowType->isDependentType() && !ThrowType->isObjCObjectPointerType()) { const PointerType *PT = ThrowType->getAs(); if (!PT || !PT->getPointeeType()->isVoidType()) return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object) << Throw->getType() << Throw->getSourceRange()); } } return new (Context) ObjCAtThrowStmt(AtLoc, Throw); } StmtResult Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, Scope *CurScope) { if (!getLangOpts().ObjCExceptions) Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; if (!Throw) { // @throw without an expression designates a rethrow (which must occur // in the context of an @catch clause). Scope *AtCatchParent = CurScope; while (AtCatchParent && !AtCatchParent->isAtCatchScope()) AtCatchParent = AtCatchParent->getParent(); if (!AtCatchParent) return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch)); } return BuildObjCAtThrowStmt(AtLoc, Throw); } ExprResult Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { ExprResult result = DefaultLvalueConversion(operand); if (result.isInvalid()) return ExprError(); operand = result.get(); // Make sure the expression type is an ObjC pointer or "void *". QualType type = operand->getType(); if (!type->isDependentType() && !type->isObjCObjectPointerType()) { const PointerType *pointerType = type->getAs(); if (!pointerType || !pointerType->getPointeeType()->isVoidType()) { if (getLangOpts().CPlusPlus) { if (RequireCompleteType(atLoc, type, diag::err_incomplete_receiver_type)) return Diag(atLoc, diag::err_objc_synchronized_expects_object) << type << operand->getSourceRange(); ExprResult result = PerformContextuallyConvertToObjCPointer(operand); if (result.isInvalid()) return ExprError(); if (!result.isUsable()) return Diag(atLoc, diag::err_objc_synchronized_expects_object) << type << operand->getSourceRange(); operand = result.get(); } else { return Diag(atLoc, diag::err_objc_synchronized_expects_object) << type << operand->getSourceRange(); } } } // The operand to @synchronized is a full-expression. return ActOnFinishFullExpr(operand); } StmtResult Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, Stmt *SyncBody) { // We can't jump into or indirect-jump out of a @synchronized block. getCurFunction()->setHasBranchProtectedScope(); return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody); } /// ActOnCXXCatchBlock - Takes an exception declaration and a handler block /// and creates a proper catch handler from them. StmtResult Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock) { // There's nothing to test that ActOnExceptionDecl didn't already test. return new (Context) CXXCatchStmt(CatchLoc, cast_or_null(ExDecl), HandlerBlock); } StmtResult Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) { getCurFunction()->setHasBranchProtectedScope(); return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body); } namespace { class CatchHandlerType { QualType QT; unsigned IsPointer : 1; // This is a special constructor to be used only with DenseMapInfo's // getEmptyKey() and getTombstoneKey() functions. friend struct llvm::DenseMapInfo; enum Unique { ForDenseMap }; CatchHandlerType(QualType QT, Unique) : QT(QT), IsPointer(false) {} public: /// Used when creating a CatchHandlerType from a handler type; will determine /// whether the type is a pointer or reference and will strip off the top /// level pointer and cv-qualifiers. CatchHandlerType(QualType Q) : QT(Q), IsPointer(false) { if (QT->isPointerType()) IsPointer = true; if (IsPointer || QT->isReferenceType()) QT = QT->getPointeeType(); QT = QT.getUnqualifiedType(); } /// Used when creating a CatchHandlerType from a base class type; pretends the /// type passed in had the pointer qualifier, does not need to get an /// unqualified type. CatchHandlerType(QualType QT, bool IsPointer) : QT(QT), IsPointer(IsPointer) {} QualType underlying() const { return QT; } bool isPointer() const { return IsPointer; } friend bool operator==(const CatchHandlerType &LHS, const CatchHandlerType &RHS) { // If the pointer qualification does not match, we can return early. if (LHS.IsPointer != RHS.IsPointer) return false; // Otherwise, check the underlying type without cv-qualifiers. return LHS.QT == RHS.QT; } }; } // namespace namespace llvm { template <> struct DenseMapInfo { static CatchHandlerType getEmptyKey() { return CatchHandlerType(DenseMapInfo::getEmptyKey(), CatchHandlerType::ForDenseMap); } static CatchHandlerType getTombstoneKey() { return CatchHandlerType(DenseMapInfo::getTombstoneKey(), CatchHandlerType::ForDenseMap); } static unsigned getHashValue(const CatchHandlerType &Base) { return DenseMapInfo::getHashValue(Base.underlying()); } static bool isEqual(const CatchHandlerType &LHS, const CatchHandlerType &RHS) { return LHS == RHS; } }; } namespace { class CatchTypePublicBases { ASTContext &Ctx; const llvm::DenseMap &TypesToCheck; const bool CheckAgainstPointer; CXXCatchStmt *FoundHandler; CanQualType FoundHandlerType; public: CatchTypePublicBases( ASTContext &Ctx, const llvm::DenseMap &T, bool C) : Ctx(Ctx), TypesToCheck(T), CheckAgainstPointer(C), FoundHandler(nullptr) {} CXXCatchStmt *getFoundHandler() const { return FoundHandler; } CanQualType getFoundHandlerType() const { return FoundHandlerType; } bool operator()(const CXXBaseSpecifier *S, CXXBasePath &) { if (S->getAccessSpecifier() == AccessSpecifier::AS_public) { CatchHandlerType Check(S->getType(), CheckAgainstPointer); const auto &M = TypesToCheck; auto I = M.find(Check); if (I != M.end()) { FoundHandler = I->second; FoundHandlerType = Ctx.getCanonicalType(S->getType()); return true; } } return false; } }; } /// ActOnCXXTryBlock - Takes a try compound-statement and a number of /// handlers and creates a try statement from them. StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, ArrayRef Handlers) { // Don't report an error if 'try' is used in system headers. if (!getLangOpts().CXXExceptions && !getSourceManager().isInSystemHeader(TryLoc)) Diag(TryLoc, diag::err_exceptions_disabled) << "try"; // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) << "try" << CurrentCUDATarget(); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try"; sema::FunctionScopeInfo *FSI = getCurFunction(); // C++ try is incompatible with SEH __try. if (!getLangOpts().Borland && FSI->FirstSEHTryLoc.isValid()) { Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; } const unsigned NumHandlers = Handlers.size(); assert(!Handlers.empty() && "The parser shouldn't call this if there are no handlers."); llvm::DenseMap HandledTypes; for (unsigned i = 0; i < NumHandlers; ++i) { CXXCatchStmt *H = cast(Handlers[i]); // Diagnose when the handler is a catch-all handler, but it isn't the last // handler for the try block. [except.handle]p5. Also, skip exception // declarations that are invalid, since we can't usefully report on them. if (!H->getExceptionDecl()) { if (i < NumHandlers - 1) return StmtError(Diag(H->getLocStart(), diag::err_early_catch_all)); continue; } else if (H->getExceptionDecl()->isInvalidDecl()) continue; // Walk the type hierarchy to diagnose when this type has already been // handled (duplication), or cannot be handled (derivation inversion). We // ignore top-level cv-qualifiers, per [except.handle]p3 CatchHandlerType HandlerCHT = (QualType)Context.getCanonicalType(H->getCaughtType()); // We can ignore whether the type is a reference or a pointer; we need the // underlying declaration type in order to get at the underlying record // decl, if there is one. QualType Underlying = HandlerCHT.underlying(); if (auto *RD = Underlying->getAsCXXRecordDecl()) { if (!RD->hasDefinition()) continue; // Check that none of the public, unambiguous base classes are in the // map ([except.handle]p1). Give the base classes the same pointer // qualification as the original type we are basing off of. This allows // comparison against the handler type using the same top-level pointer // as the original type. CXXBasePaths Paths; Paths.setOrigin(RD); CatchTypePublicBases CTPB(Context, HandledTypes, HandlerCHT.isPointer()); if (RD->lookupInBases(CTPB, Paths)) { const CXXCatchStmt *Problem = CTPB.getFoundHandler(); if (!Paths.isAmbiguous(CTPB.getFoundHandlerType())) { Diag(H->getExceptionDecl()->getTypeSpecStartLoc(), diag::warn_exception_caught_by_earlier_handler) << H->getCaughtType(); Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(), diag::note_previous_exception_handler) << Problem->getCaughtType(); } } } // Add the type the list of ones we have handled; diagnose if we've already // handled it. auto R = HandledTypes.insert(std::make_pair(H->getCaughtType(), H)); if (!R.second) { const CXXCatchStmt *Problem = R.first->second; Diag(H->getExceptionDecl()->getTypeSpecStartLoc(), diag::warn_exception_caught_by_earlier_handler) << H->getCaughtType(); Diag(Problem->getExceptionDecl()->getTypeSpecStartLoc(), diag::note_previous_exception_handler) << Problem->getCaughtType(); } } FSI->setHasCXXTry(TryLoc); return CXXTryStmt::Create(Context, TryLoc, TryBlock, Handlers); } StmtResult Sema::ActOnSEHTryBlock(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler) { assert(TryBlock && Handler); sema::FunctionScopeInfo *FSI = getCurFunction(); // SEH __try is incompatible with C++ try. Borland appears to support this, // however. if (!getLangOpts().Borland) { if (FSI->FirstCXXTryLoc.isValid()) { Diag(TryLoc, diag::err_mixing_cxx_try_seh_try); Diag(FSI->FirstCXXTryLoc, diag::note_conflicting_try_here) << "'try'"; } } FSI->setHasSEHTry(TryLoc); // Reject __try in Obj-C methods, blocks, and captured decls, since we don't // track if they use SEH. DeclContext *DC = CurContext; while (DC && !DC->isFunctionOrMethod()) DC = DC->getParent(); FunctionDecl *FD = dyn_cast_or_null(DC); if (FD) FD->setUsesSEHTry(true); else Diag(TryLoc, diag::err_seh_try_outside_functions); // Reject __try on unsupported targets. if (!Context.getTargetInfo().isSEHTrySupported()) Diag(TryLoc, diag::err_seh_try_unsupported); return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler); } StmtResult Sema::ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) { assert(FilterExpr && Block); if(!FilterExpr->getType()->isIntegerType()) { return StmtError(Diag(FilterExpr->getExprLoc(), diag::err_filter_expression_integral) << FilterExpr->getType()); } return SEHExceptStmt::Create(Context,Loc,FilterExpr,Block); } void Sema::ActOnStartSEHFinallyBlock() { CurrentSEHFinally.push_back(CurScope); } void Sema::ActOnAbortSEHFinallyBlock() { CurrentSEHFinally.pop_back(); } StmtResult Sema::ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block) { assert(Block); CurrentSEHFinally.pop_back(); return SEHFinallyStmt::Create(Context, Loc, Block); } StmtResult Sema::ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope) { Scope *SEHTryParent = CurScope; while (SEHTryParent && !SEHTryParent->isSEHTryScope()) SEHTryParent = SEHTryParent->getParent(); if (!SEHTryParent) return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try)); CheckJumpOutOfSEHFinally(*this, Loc, *SEHTryParent); return new (Context) SEHLeaveStmt(Loc); } StmtResult Sema::BuildMSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, NestedNameSpecifierLoc QualifierLoc, DeclarationNameInfo NameInfo, Stmt *Nested) { return new (Context) MSDependentExistsStmt(KeywordLoc, IsIfExists, QualifierLoc, NameInfo, cast(Nested)); } StmtResult Sema::ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, CXXScopeSpec &SS, UnqualifiedId &Name, Stmt *Nested) { return BuildMSDependentExistsStmt(KeywordLoc, IsIfExists, SS.getWithLocInContext(Context), GetNameFromUnqualifiedId(Name), Nested); } RecordDecl* Sema::CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, unsigned NumParams) { DeclContext *DC = CurContext; while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); RecordDecl *RD = nullptr; if (getLangOpts().CPlusPlus) RD = CXXRecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr); else RD = RecordDecl::Create(Context, TTK_Struct, DC, Loc, Loc, /*Id=*/nullptr); RD->setCapturedRecord(); DC->addDecl(RD); RD->setImplicit(); RD->startDefinition(); assert(NumParams > 0 && "CapturedStmt requires context parameter"); CD = CapturedDecl::Create(Context, CurContext, NumParams); DC->addDecl(CD); return RD; } static void buildCapturedStmtCaptureList( SmallVectorImpl &Captures, SmallVectorImpl &CaptureInits, ArrayRef Candidates) { typedef ArrayRef::const_iterator CaptureIter; for (CaptureIter Cap = Candidates.begin(); Cap != Candidates.end(); ++Cap) { if (Cap->isThisCapture()) { Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_This)); CaptureInits.push_back(Cap->getInitExpr()); continue; } else if (Cap->isVLATypeCapture()) { Captures.push_back( CapturedStmt::Capture(Cap->getLocation(), CapturedStmt::VCK_VLAType)); CaptureInits.push_back(nullptr); continue; } Captures.push_back(CapturedStmt::Capture(Cap->getLocation(), Cap->isReferenceCapture() ? CapturedStmt::VCK_ByRef : CapturedStmt::VCK_ByCopy, Cap->getVariable())); CaptureInits.push_back(Cap->getInitExpr()); } } void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams) { CapturedDecl *CD = nullptr; RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, NumParams); // Build the context parameter DeclContext *DC = CapturedDecl::castToDeclContext(CD); IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); ImplicitParamDecl *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); DC->addDecl(Param); CD->setContextParam(0, Param); // Enter the capturing scope for this captured region. PushCapturedRegionScope(CurScope, CD, RD, Kind); if (CurScope) PushDeclContext(CurScope, CD); else CurContext = CD; PushExpressionEvaluationContext(PotentiallyEvaluated); } void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, ArrayRef Params) { CapturedDecl *CD = nullptr; RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, Params.size()); // Build the context parameter DeclContext *DC = CapturedDecl::castToDeclContext(CD); bool ContextIsFound = false; unsigned ParamNum = 0; for (ArrayRef::iterator I = Params.begin(), E = Params.end(); I != E; ++I, ++ParamNum) { if (I->second.isNull()) { assert(!ContextIsFound && "null type has been found already for '__context' parameter"); IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); ImplicitParamDecl *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); ContextIsFound = true; } else { IdentifierInfo *ParamName = &Context.Idents.get(I->first); ImplicitParamDecl *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, I->second); DC->addDecl(Param); CD->setParam(ParamNum, Param); } } assert(ContextIsFound && "no null type for '__context' parameter"); if (!ContextIsFound) { // Add __context implicitly if it is not specified. IdentifierInfo *ParamName = &Context.Idents.get("__context"); QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); ImplicitParamDecl *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType); DC->addDecl(Param); CD->setContextParam(ParamNum, Param); } // Enter the capturing scope for this captured region. PushCapturedRegionScope(CurScope, CD, RD, Kind); if (CurScope) PushDeclContext(CurScope, CD); else CurContext = CD; PushExpressionEvaluationContext(PotentiallyEvaluated); } void Sema::ActOnCapturedRegionError() { DiscardCleanupsInEvaluationContext(); PopExpressionEvaluationContext(); CapturedRegionScopeInfo *RSI = getCurCapturedRegion(); RecordDecl *Record = RSI->TheRecordDecl; Record->setInvalidDecl(); SmallVector Fields(Record->fields()); ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields, SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr); PopDeclContext(); PopFunctionScopeInfo(); } StmtResult Sema::ActOnCapturedRegionEnd(Stmt *S) { CapturedRegionScopeInfo *RSI = getCurCapturedRegion(); SmallVector Captures; SmallVector CaptureInits; buildCapturedStmtCaptureList(Captures, CaptureInits, RSI->Captures); CapturedDecl *CD = RSI->TheCapturedDecl; RecordDecl *RD = RSI->TheRecordDecl; CapturedStmt *Res = CapturedStmt::Create( getASTContext(), S, static_cast(RSI->CapRegionKind), Captures, CaptureInits, CD, RD); CD->setBody(Res->getCapturedStmt()); RD->completeDefinition(); DiscardCleanupsInEvaluationContext(); PopExpressionEvaluationContext(); PopDeclContext(); PopFunctionScopeInfo(); return Res; } Index: vendor/clang/dist/lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- vendor/clang/dist/lib/Sema/SemaTemplateVariadic.cpp (revision 313882) +++ vendor/clang/dist/lib/Sema/SemaTemplateVariadic.cpp (revision 313883) @@ -1,1083 +1,1090 @@ //===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/ // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. //===----------------------------------------------------------------------===/ // // This file implements semantic analysis for C++0x variadic templates. //===----------------------------------------------------------------------===/ #include "clang/Sema/Sema.h" #include "TypeLocBuilder.h" #include "clang/AST/Expr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" using namespace clang; //---------------------------------------------------------------------------- // Visitor that collects unexpanded parameter packs //---------------------------------------------------------------------------- namespace { /// \brief A class that collects unexpanded parameter packs. class CollectUnexpandedParameterPacksVisitor : public RecursiveASTVisitor { typedef RecursiveASTVisitor inherited; SmallVectorImpl &Unexpanded; bool InLambda; public: explicit CollectUnexpandedParameterPacksVisitor( SmallVectorImpl &Unexpanded) : Unexpanded(Unexpanded), InLambda(false) { } bool shouldWalkTypesOfTypeLocs() const { return false; } //------------------------------------------------------------------------ // Recording occurrences of (unexpanded) parameter packs. //------------------------------------------------------------------------ /// \brief Record occurrences of template type parameter packs. bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { if (TL.getTypePtr()->isParameterPack()) Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc())); return true; } /// \brief Record occurrences of template type parameter packs /// when we don't have proper source-location information for /// them. /// /// Ideally, this routine would never be used. bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { if (T->isParameterPack()) Unexpanded.push_back(std::make_pair(T, SourceLocation())); return true; } /// \brief Record occurrences of function and non-type template /// parameter packs in an expression. bool VisitDeclRefExpr(DeclRefExpr *E) { if (E->getDecl()->isParameterPack()) Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation())); return true; } /// \brief Record occurrences of template template parameter packs. bool TraverseTemplateName(TemplateName Template) { if (TemplateTemplateParmDecl *TTP = dyn_cast_or_null( Template.getAsTemplateDecl())) if (TTP->isParameterPack()) Unexpanded.push_back(std::make_pair(TTP, SourceLocation())); return inherited::TraverseTemplateName(Template); } /// \brief Suppress traversal into Objective-C container literal /// elements that are pack expansions. bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { if (!E->containsUnexpandedParameterPack()) return true; for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { ObjCDictionaryElement Element = E->getKeyValueElement(I); if (Element.isPackExpansion()) continue; TraverseStmt(Element.Key); TraverseStmt(Element.Value); } return true; } //------------------------------------------------------------------------ // Pruning the search for unexpanded parameter packs. //------------------------------------------------------------------------ /// \brief Suppress traversal into statements and expressions that /// do not contain unexpanded parameter packs. bool TraverseStmt(Stmt *S) { Expr *E = dyn_cast_or_null(S); if ((E && E->containsUnexpandedParameterPack()) || InLambda) return inherited::TraverseStmt(S); return true; } /// \brief Suppress traversal into types that do not contain /// unexpanded parameter packs. bool TraverseType(QualType T) { if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda) return inherited::TraverseType(T); return true; } /// \brief Suppress traversel into types with location information /// that do not contain unexpanded parameter packs. bool TraverseTypeLoc(TypeLoc TL) { if ((!TL.getType().isNull() && TL.getType()->containsUnexpandedParameterPack()) || InLambda) return inherited::TraverseTypeLoc(TL); return true; } /// \brief Suppress traversal of non-parameter declarations, since /// they cannot contain unexpanded parameter packs. bool TraverseDecl(Decl *D) { if ((D && isa(D)) || InLambda) return inherited::TraverseDecl(D); return true; } /// \brief Suppress traversal of template argument pack expansions. bool TraverseTemplateArgument(const TemplateArgument &Arg) { if (Arg.isPackExpansion()) return true; return inherited::TraverseTemplateArgument(Arg); } /// \brief Suppress traversal of template argument pack expansions. bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { if (ArgLoc.getArgument().isPackExpansion()) return true; return inherited::TraverseTemplateArgumentLoc(ArgLoc); } /// \brief Note whether we're traversing a lambda containing an unexpanded /// parameter pack. In this case, the unexpanded pack can occur anywhere, /// including all the places where we normally wouldn't look. Within a /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit /// outside an expression. bool TraverseLambdaExpr(LambdaExpr *Lambda) { // The ContainsUnexpandedParameterPack bit on a lambda is always correct, // even if it's contained within another lambda. if (!Lambda->containsUnexpandedParameterPack()) return true; bool WasInLambda = InLambda; InLambda = true; // If any capture names a function parameter pack, that pack is expanded // when the lambda is expanded. for (LambdaExpr::capture_iterator I = Lambda->capture_begin(), E = Lambda->capture_end(); I != E; ++I) { if (I->capturesVariable()) { VarDecl *VD = I->getCapturedVar(); if (VD->isParameterPack()) Unexpanded.push_back(std::make_pair(VD, I->getLocation())); } } inherited::TraverseLambdaExpr(Lambda); InLambda = WasInLambda; return true; } }; } /// \brief Determine whether it's possible for an unexpanded parameter pack to /// be valid in this location. This only happens when we're in a declaration /// that is nested within an expression that could be expanded, such as a /// lambda-expression within a function call. /// /// This is conservatively correct, but may claim that some unexpanded packs are /// permitted when they are not. bool Sema::isUnexpandedParameterPackPermitted() { for (auto *SI : FunctionScopes) if (isa(SI)) return true; return false; } /// \brief Diagnose all of the unexpanded parameter packs in the given /// vector. bool Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc, UnexpandedParameterPackContext UPPC, ArrayRef Unexpanded) { if (Unexpanded.empty()) return false; // If we are within a lambda expression, that lambda contains an unexpanded // parameter pack, and we are done. // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it // later. for (unsigned N = FunctionScopes.size(); N; --N) { if (sema::LambdaScopeInfo *LSI = dyn_cast(FunctionScopes[N-1])) { LSI->ContainsUnexpandedParameterPack = true; return false; } } SmallVector Locations; SmallVector Names; llvm::SmallPtrSet NamesKnown; for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { IdentifierInfo *Name = nullptr; if (const TemplateTypeParmType *TTP = Unexpanded[I].first.dyn_cast()) Name = TTP->getIdentifier(); else Name = Unexpanded[I].first.get()->getIdentifier(); if (Name && NamesKnown.insert(Name).second) Names.push_back(Name); if (Unexpanded[I].second.isValid()) Locations.push_back(Unexpanded[I].second); } DiagnosticBuilder DB = Diag(Loc, diag::err_unexpanded_parameter_pack) << (int)UPPC << (int)Names.size(); for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I) DB << Names[I]; for (unsigned I = 0, N = Locations.size(); I != N; ++I) DB << SourceRange(Locations[I]); return true; } bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC) { // C++0x [temp.variadic]p5: // An appearance of a name of a parameter pack that is not expanded is // ill-formed. if (!T->getType()->containsUnexpandedParameterPack()) return false; SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc( T->getTypeLoc()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, UnexpandedParameterPackContext UPPC) { // C++0x [temp.variadic]p5: // An appearance of a name of a parameter pack that is not expanded is // ill-formed. if (!E->containsUnexpandedParameterPack()) return false; SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); return DiagnoseUnexpandedParameterPacks(E->getLocStart(), UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, UnexpandedParameterPackContext UPPC) { // C++0x [temp.variadic]p5: // An appearance of a name of a parameter pack that is not expanded is // ill-formed. if (!SS.getScopeRep() || !SS.getScopeRep()->containsUnexpandedParameterPack()) return false; SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseNestedNameSpecifier(SS.getScopeRep()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(), UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, UnexpandedParameterPackContext UPPC) { // C++0x [temp.variadic]p5: // An appearance of a name of a parameter pack that is not expanded is // ill-formed. switch (NameInfo.getName().getNameKind()) { case DeclarationName::Identifier: case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: case DeclarationName::CXXOperatorName: case DeclarationName::CXXLiteralOperatorName: case DeclarationName::CXXUsingDirective: return false; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: // FIXME: We shouldn't need this null check! if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC); if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack()) return false; break; } SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseType(NameInfo.getName().getCXXNameType()); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, TemplateName Template, UnexpandedParameterPackContext UPPC) { if (Template.isNull() || !Template.containsUnexpandedParameterPack()) return false; SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateName(Template); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded); } bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, UnexpandedParameterPackContext UPPC) { if (Arg.getArgument().isNull() || !Arg.getArgument().containsUnexpandedParameterPack()) return false; SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateArgumentLoc(Arg); assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded); } void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateArgument(Arg); } void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg, SmallVectorImpl &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseTemplateArgumentLoc(Arg); } void Sema::collectUnexpandedParameterPacks(QualType T, SmallVectorImpl &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T); } void Sema::collectUnexpandedParameterPacks(TypeLoc TL, SmallVectorImpl &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL); } void Sema::collectUnexpandedParameterPacks( NestedNameSpecifierLoc NNS, SmallVectorImpl &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseNestedNameSpecifierLoc(NNS); } void Sema::collectUnexpandedParameterPacks( const DeclarationNameInfo &NameInfo, SmallVectorImpl &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseDeclarationNameInfo(NameInfo); } ParsedTemplateArgument Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, SourceLocation EllipsisLoc) { if (Arg.isInvalid()) return Arg; switch (Arg.getKind()) { case ParsedTemplateArgument::Type: { TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc); if (Result.isInvalid()) return ParsedTemplateArgument(); return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), Arg.getLocation()); } case ParsedTemplateArgument::NonType: { ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc); if (Result.isInvalid()) return ParsedTemplateArgument(); return ParsedTemplateArgument(Arg.getKind(), Result.get(), Arg.getLocation()); } case ParsedTemplateArgument::Template: if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) { SourceRange R(Arg.getLocation()); if (Arg.getScopeSpec().isValid()) R.setBegin(Arg.getScopeSpec().getBeginLoc()); Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << R; return ParsedTemplateArgument(); } return Arg.getTemplatePackExpansion(EllipsisLoc); } llvm_unreachable("Unhandled template argument kind?"); } TypeResult Sema::ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc) { TypeSourceInfo *TSInfo; GetTypeFromParser(Type, &TSInfo); if (!TSInfo) return true; TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, None); if (!TSResult) return true; return CreateParsedType(TSResult->getType(), TSResult); } TypeSourceInfo * Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, Optional NumExpansions) { // Create the pack expansion type and source-location information. QualType Result = CheckPackExpansion(Pattern->getType(), Pattern->getTypeLoc().getSourceRange(), EllipsisLoc, NumExpansions); if (Result.isNull()) return nullptr; TypeLocBuilder TLB; TLB.pushFullCopy(Pattern->getTypeLoc()); PackExpansionTypeLoc TL = TLB.push(Result); TL.setEllipsisLoc(EllipsisLoc); return TLB.getTypeSourceInfo(Context, Result); } QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange, SourceLocation EllipsisLoc, Optional NumExpansions) { // C++0x [temp.variadic]p5: // The pattern of a pack expansion shall name one or more // parameter packs that are not expanded by a nested pack // expansion. if (!Pattern->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << PatternRange; return QualType(); } return Context.getPackExpansionType(Pattern, NumExpansions); } ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { return CheckPackExpansion(Pattern, EllipsisLoc, None); } ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, Optional NumExpansions) { if (!Pattern) return ExprError(); // C++0x [temp.variadic]p5: // The pattern of a pack expansion shall name one or more // parameter packs that are not expanded by a nested pack // expansion. if (!Pattern->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << Pattern->getSourceRange(); return ExprError(); } // Create the pack expansion expression and source-location information. return new (Context) PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions); } /// \brief Retrieve the depth and index of a parameter pack. static std::pair getDepthAndIndex(NamedDecl *ND) { if (TemplateTypeParmDecl *TTP = dyn_cast(ND)) return std::make_pair(TTP->getDepth(), TTP->getIndex()); if (NonTypeTemplateParmDecl *NTTP = dyn_cast(ND)) return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); TemplateTemplateParmDecl *TTP = cast(ND); return std::make_pair(TTP->getDepth(), TTP->getIndex()); } bool Sema::CheckParameterPacksForExpansion( SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, bool &RetainExpansion, Optional &NumExpansions) { ShouldExpand = true; RetainExpansion = false; std::pair FirstPack; bool HaveFirstPack = false; for (ArrayRef::iterator i = Unexpanded.begin(), end = Unexpanded.end(); i != end; ++i) { // Compute the depth and index for this parameter pack. unsigned Depth = 0, Index = 0; IdentifierInfo *Name; bool IsFunctionParameterPack = false; if (const TemplateTypeParmType *TTP = i->first.dyn_cast()) { Depth = TTP->getDepth(); Index = TTP->getIndex(); Name = TTP->getIdentifier(); } else { NamedDecl *ND = i->first.get(); if (isa(ND)) IsFunctionParameterPack = true; else std::tie(Depth, Index) = getDepthAndIndex(ND); Name = ND->getIdentifier(); } // Determine the size of this argument pack. unsigned NewPackSize; if (IsFunctionParameterPack) { // Figure out whether we're instantiating to an argument pack or not. typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; llvm::PointerUnion *Instantiation = CurrentInstantiationScope->findInstantiationOf( i->first.get()); if (Instantiation->is()) { // We could expand this function parameter pack. NewPackSize = Instantiation->get()->size(); } else { // We can't expand this function parameter pack, so we can't expand // the pack expansion. ShouldExpand = false; continue; } } else { // If we don't have a template argument at this depth/index, then we // cannot expand the pack expansion. Make a note of this, but we still // want to check any parameter packs we *do* have arguments for. if (Depth >= TemplateArgs.getNumLevels() || !TemplateArgs.hasTemplateArgument(Depth, Index)) { ShouldExpand = false; continue; } // Determine the size of the argument pack. NewPackSize = TemplateArgs(Depth, Index).pack_size(); } // C++0x [temp.arg.explicit]p9: // Template argument deduction can extend the sequence of template // arguments corresponding to a template parameter pack, even when the // sequence contains explicitly specified template arguments. if (!IsFunctionParameterPack && CurrentInstantiationScope) { if (NamedDecl *PartialPack = CurrentInstantiationScope->getPartiallySubstitutedPack()){ unsigned PartialDepth, PartialIndex; std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); if (PartialDepth == Depth && PartialIndex == Index) RetainExpansion = true; } } if (!NumExpansions) { // The is the first pack we've seen for which we have an argument. // Record it. NumExpansions = NewPackSize; FirstPack.first = Name; FirstPack.second = i->second; HaveFirstPack = true; continue; } if (NewPackSize != *NumExpansions) { // C++0x [temp.variadic]p5: // All of the parameter packs expanded by a pack expansion shall have // the same number of arguments specified. if (HaveFirstPack) Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) << FirstPack.first << Name << *NumExpansions << NewPackSize << SourceRange(FirstPack.second) << SourceRange(i->second); else Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) << Name << *NumExpansions << NewPackSize << SourceRange(i->second); return true; } } return false; } Optional Sema::getNumArgumentsInExpansion(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs) { QualType Pattern = cast(T)->getPattern(); SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); Optional Result; for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { // Compute the depth and index for this parameter pack. unsigned Depth; unsigned Index; if (const TemplateTypeParmType *TTP = Unexpanded[I].first.dyn_cast()) { Depth = TTP->getDepth(); Index = TTP->getIndex(); } else { NamedDecl *ND = Unexpanded[I].first.get(); if (isa(ND)) { // Function parameter pack. typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; llvm::PointerUnion *Instantiation = CurrentInstantiationScope->findInstantiationOf( Unexpanded[I].first.get()); if (Instantiation->is()) // The pattern refers to an unexpanded pack. We're not ready to expand // this pack yet. return None; unsigned Size = Instantiation->get()->size(); assert((!Result || *Result == Size) && "inconsistent pack sizes"); Result = Size; continue; } std::tie(Depth, Index) = getDepthAndIndex(ND); } if (Depth >= TemplateArgs.getNumLevels() || !TemplateArgs.hasTemplateArgument(Depth, Index)) // The pattern refers to an unknown template argument. We're not ready to // expand this pack yet. return None; // Determine the size of the argument pack. unsigned Size = TemplateArgs(Depth, Index).pack_size(); assert((!Result || *Result == Size) && "inconsistent pack sizes"); Result = Size; } return Result; } bool Sema::containsUnexpandedParameterPacks(Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); switch (DS.getTypeSpecType()) { case TST_typename: case TST_typeofType: case TST_underlyingType: case TST_atomic: { QualType T = DS.getRepAsType().get(); if (!T.isNull() && T->containsUnexpandedParameterPack()) return true; break; } case TST_typeofExpr: case TST_decltype: if (DS.getRepAsExpr() && DS.getRepAsExpr()->containsUnexpandedParameterPack()) return true; break; case TST_unspecified: case TST_void: case TST_char: case TST_wchar: case TST_char16: case TST_char32: case TST_int: case TST_int128: case TST_half: case TST_float: case TST_double: case TST_float128: case TST_bool: case TST_decimal32: case TST_decimal64: case TST_decimal128: case TST_enum: case TST_union: case TST_struct: case TST_interface: case TST_class: case TST_auto: case TST_auto_type: case TST_decltype_auto: #define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: #include "clang/Basic/OpenCLImageTypes.def" case TST_unknown_anytype: case TST_error: break; } for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) { const DeclaratorChunk &Chunk = D.getTypeObject(I); switch (Chunk.Kind) { case DeclaratorChunk::Pointer: case DeclaratorChunk::Reference: case DeclaratorChunk::Paren: case DeclaratorChunk::Pipe: case DeclaratorChunk::BlockPointer: // These declarator chunks cannot contain any parameter packs. break; case DeclaratorChunk::Array: if (Chunk.Arr.NumElts && Chunk.Arr.NumElts->containsUnexpandedParameterPack()) return true; break; case DeclaratorChunk::Function: for (unsigned i = 0, e = Chunk.Fun.NumParams; i != e; ++i) { ParmVarDecl *Param = cast(Chunk.Fun.Params[i].Param); QualType ParamTy = Param->getType(); assert(!ParamTy.isNull() && "Couldn't parse type?"); if (ParamTy->containsUnexpandedParameterPack()) return true; } if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) { for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) { if (Chunk.Fun.Exceptions[i] .Ty.get() ->containsUnexpandedParameterPack()) return true; } } else if (Chunk.Fun.getExceptionSpecType() == EST_ComputedNoexcept && Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack()) return true; if (Chunk.Fun.hasTrailingReturnType()) { QualType T = Chunk.Fun.getTrailingReturnType().get(); if (!T.isNull() && T->containsUnexpandedParameterPack()) return true; } break; case DeclaratorChunk::MemberPointer: if (Chunk.Mem.Scope().getScopeRep() && Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack()) return true; break; } } return false; } namespace { // Callback to only accept typo corrections that refer to parameter packs. class ParameterPackValidatorCCC : public CorrectionCandidateCallback { public: bool ValidateCandidate(const TypoCorrection &candidate) override { NamedDecl *ND = candidate.getCorrectionDecl(); return ND && ND->isParameterPack(); } }; } /// \brief Called when an expression computing the size of a parameter pack /// is parsed. /// /// \code /// template struct count { /// static const unsigned value = sizeof...(Types); /// }; /// \endcode /// // /// \param OpLoc The location of the "sizeof" keyword. /// \param Name The name of the parameter pack whose size will be determined. /// \param NameLoc The source location of the name of the parameter pack. /// \param RParenLoc The location of the closing parentheses. ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc, IdentifierInfo &Name, SourceLocation NameLoc, SourceLocation RParenLoc) { // C++0x [expr.sizeof]p5: // The identifier in a sizeof... expression shall name a parameter pack. LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName); LookupName(R, S); NamedDecl *ParameterPack = nullptr; switch (R.getResultKind()) { case LookupResult::Found: ParameterPack = R.getFoundDecl(); break; case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr, llvm::make_unique(), CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name, PDiag(diag::note_parameter_pack_here)); ParameterPack = Corrected.getCorrectionDecl(); } case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: break; case LookupResult::Ambiguous: DiagnoseAmbiguousLookup(R); return ExprError(); } if (!ParameterPack || !ParameterPack->isParameterPack()) { Diag(NameLoc, diag::err_sizeof_pack_no_pack_name) << &Name; return ExprError(); } MarkAnyDeclReferenced(OpLoc, ParameterPack, true); return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc, RParenLoc); } TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis, Optional &NumExpansions) const { const TemplateArgument &Argument = OrigLoc.getArgument(); assert(Argument.isPackExpansion()); switch (Argument.getKind()) { case TemplateArgument::Type: { // FIXME: We shouldn't ever have to worry about missing // type-source info! TypeSourceInfo *ExpansionTSInfo = OrigLoc.getTypeSourceInfo(); if (!ExpansionTSInfo) ExpansionTSInfo = Context.getTrivialTypeSourceInfo(Argument.getAsType(), Ellipsis); PackExpansionTypeLoc Expansion = ExpansionTSInfo->getTypeLoc().castAs(); Ellipsis = Expansion.getEllipsisLoc(); TypeLoc Pattern = Expansion.getPatternLoc(); NumExpansions = Expansion.getTypePtr()->getNumExpansions(); // We need to copy the TypeLoc because TemplateArgumentLocs store a // TypeSourceInfo. // FIXME: Find some way to avoid the copy? TypeLocBuilder TLB; TLB.pushFullCopy(Pattern); TypeSourceInfo *PatternTSInfo = TLB.getTypeSourceInfo(Context, Pattern.getType()); return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), PatternTSInfo); } case TemplateArgument::Expression: { PackExpansionExpr *Expansion = cast(Argument.getAsExpr()); Expr *Pattern = Expansion->getPattern(); Ellipsis = Expansion->getEllipsisLoc(); NumExpansions = Expansion->getNumExpansions(); return TemplateArgumentLoc(Pattern, Pattern); } case TemplateArgument::TemplateExpansion: Ellipsis = OrigLoc.getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); return TemplateArgumentLoc(Argument.getPackExpansionPattern(), OrigLoc.getTemplateQualifierLoc(), OrigLoc.getTemplateNameLoc()); case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::Template: case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: return TemplateArgumentLoc(); } llvm_unreachable("Invalid TemplateArgument Kind!"); } Optional Sema::getFullyPackExpandedSize(TemplateArgument Arg) { assert(Arg.containsUnexpandedParameterPack()); // If this is a substituted pack, grab that pack. If not, we don't know // the size yet. // FIXME: We could find a size in more cases by looking for a substituted // pack anywhere within this argument, but that's not necessary in the common // case for 'sizeof...(A)' handling. TemplateArgument Pack; switch (Arg.getKind()) { case TemplateArgument::Type: if (auto *Subst = Arg.getAsType()->getAs()) Pack = Subst->getArgumentPack(); else return None; break; case TemplateArgument::Expression: if (auto *Subst = dyn_cast(Arg.getAsExpr())) Pack = Subst->getArgumentPack(); else if (auto *Subst = dyn_cast(Arg.getAsExpr())) { for (ParmVarDecl *PD : *Subst) if (PD->isParameterPack()) return None; return Subst->getNumExpansions(); } else return None; break; case TemplateArgument::Template: if (SubstTemplateTemplateParmPackStorage *Subst = Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack()) Pack = Subst->getArgumentPack(); else return None; break; case TemplateArgument::Declaration: case TemplateArgument::NullPtr: case TemplateArgument::TemplateExpansion: case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: return None; } // Check that no argument in the pack is itself a pack expansion. for (TemplateArgument Elem : Pack.pack_elements()) { // There's no point recursing in this case; we would have already // expanded this pack expansion into the enclosing pack if we could. if (Elem.isPackExpansion()) return None; } return Pack.pack_size(); } static void CheckFoldOperand(Sema &S, Expr *E) { if (!E) return; E = E->IgnoreImpCasts(); auto *OCE = dyn_cast(E); if ((OCE && OCE->isInfixBinaryOp()) || isa(E) || isa(E)) { S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand) << E->getSourceRange() << FixItHint::CreateInsertion(E->getLocStart(), "(") << FixItHint::CreateInsertion(E->getLocEnd(), ")"); } } ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, tok::TokenKind Operator, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc) { // LHS and RHS must be cast-expressions. We allow an arbitrary expression // in the parser and reduce down to just cast-expressions here. CheckFoldOperand(*this, LHS); CheckFoldOperand(*this, RHS); + auto DiscardOperands = [&] { + CorrectDelayedTyposInExpr(LHS); + CorrectDelayedTyposInExpr(RHS); + }; + // [expr.prim.fold]p3: // In a binary fold, op1 and op2 shall be the same fold-operator, and // either e1 shall contain an unexpanded parameter pack or e2 shall contain // an unexpanded parameter pack, but not both. if (LHS && RHS && LHS->containsUnexpandedParameterPack() == RHS->containsUnexpandedParameterPack()) { + DiscardOperands(); return Diag(EllipsisLoc, LHS->containsUnexpandedParameterPack() ? diag::err_fold_expression_packs_both_sides : diag::err_pack_expansion_without_parameter_packs) << LHS->getSourceRange() << RHS->getSourceRange(); } // [expr.prim.fold]p2: // In a unary fold, the cast-expression shall contain an unexpanded // parameter pack. if (!LHS || !RHS) { Expr *Pack = LHS ? LHS : RHS; assert(Pack && "fold expression with neither LHS nor RHS"); + DiscardOperands(); if (!Pack->containsUnexpandedParameterPack()) return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << Pack->getSourceRange(); } BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator); return BuildCXXFoldExpr(LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc); } ExprResult Sema::BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Operator, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc) { return new (Context) CXXFoldExpr(Context.DependentTy, LParenLoc, LHS, Operator, EllipsisLoc, RHS, RParenLoc); } ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, BinaryOperatorKind Operator) { // [temp.variadic]p9: // If N is zero for a unary fold-expression, the value of the expression is // && -> true // || -> false // , -> void() // if the operator is not listed [above], the instantiation is ill-formed. // // Note that we need to use something like int() here, not merely 0, to // prevent the result from being a null pointer constant. QualType ScalarType; switch (Operator) { case BO_LOr: return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_false); case BO_LAnd: return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_true); case BO_Comma: ScalarType = Context.VoidTy; break; default: return Diag(EllipsisLoc, diag::err_fold_expression_empty) << BinaryOperator::getOpcodeStr(Operator); } return new (Context) CXXScalarValueInitExpr( ScalarType, Context.getTrivialTypeSourceInfo(ScalarType, EllipsisLoc), EllipsisLoc); } Index: vendor/clang/dist/test/CodeGen/object-size.c =================================================================== --- vendor/clang/dist/test/CodeGen/object-size.c (revision 313882) +++ vendor/clang/dist/test/CodeGen/object-size.c (revision 313883) @@ -1,551 +1,570 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s #define strcpy(dest, src) \ ((__builtin_object_size(dest, 0) != -1ULL) \ ? __builtin___strcpy_chk (dest, src, __builtin_object_size(dest, 1)) \ : __inline_strcpy_chk(dest, src)) static char *__inline_strcpy_chk (char *dest, const char *src) { return __builtin___strcpy_chk(dest, src, __builtin_object_size(dest, 1)); } char gbuf[63]; char *gp; int gi, gj; // CHECK-LABEL: define void @test1 void test1() { // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 0, i64 4), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i64 59) strcpy(&gbuf[4], "Hi there"); } // CHECK-LABEL: define void @test2 void test2() { // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i64 63) strcpy(gbuf, "Hi there"); } // CHECK-LABEL: define void @test3 void test3() { // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 1, i64 37), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i64 0) strcpy(&gbuf[100], "Hi there"); } // CHECK-LABEL: define void @test4 void test4() { // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i64 0, i64 -1), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i64 0) strcpy((char*)(void*)&gbuf[-1], "Hi there"); } // CHECK-LABEL: define void @test5 void test5() { // CHECK: = load i8*, i8** @gp // CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) strcpy(gp, "Hi there"); } // CHECK-LABEL: define void @test6 void test6() { char buf[57]; // CHECK: = call i8* @__strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i64 53) strcpy(&buf[4], "Hi there"); } // CHECK-LABEL: define void @test7 void test7() { int i; // Ensure we only evaluate the side-effect once. // CHECK: = add // CHECK-NOT: = add // CHECK: = call i8* @__strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i64 63) strcpy((++i, gbuf), "Hi there"); } // CHECK-LABEL: define void @test8 void test8() { char *buf[50]; // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(buf[++gi], "Hi there"); } // CHECK-LABEL: define void @test9 void test9() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy((char *)((++gi) + gj), "Hi there"); } // CHECK-LABEL: define void @test10 char **p; void test10() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(*(++p), "Hi there"); } // CHECK-LABEL: define void @test11 void test11() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* getelementptr inbounds ([63 x i8], [63 x i8]* @gbuf, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(gp = gbuf, "Hi there"); } // CHECK-LABEL: define void @test12 void test12() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(++gp, "Hi there"); } // CHECK-LABEL: define void @test13 void test13() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(gp++, "Hi there"); } // CHECK-LABEL: define void @test14 void test14() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(--gp, "Hi there"); } // CHECK-LABEL: define void @test15 void test15() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{..*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(gp--, "Hi there"); } // CHECK-LABEL: define void @test16 void test16() { // CHECK-NOT: __strcpy_chk // CHECK: = call i8* @__inline_strcpy_chk(i8* %{{.*}}, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0)) strcpy(gp += 1, "Hi there"); } // CHECK-LABEL: @test17 void test17() { // CHECK: store i32 -1 gi = __builtin_object_size(gp++, 0); // CHECK: store i32 -1 gi = __builtin_object_size(gp++, 1); // CHECK: store i32 0 gi = __builtin_object_size(gp++, 2); // CHECK: store i32 0 gi = __builtin_object_size(gp++, 3); } // CHECK-LABEL: @test18 unsigned test18(int cond) { int a[4], b[4]; // CHECK: phi i32* // CHECK: call i64 @llvm.objectsize.i64 return __builtin_object_size(cond ? a : b, 0); } // CHECK-LABEL: @test19 void test19() { struct { int a, b; } foo; // CHECK: store i32 8 gi = __builtin_object_size(&foo.a, 0); // CHECK: store i32 4 gi = __builtin_object_size(&foo.a, 1); // CHECK: store i32 8 gi = __builtin_object_size(&foo.a, 2); // CHECK: store i32 4 gi = __builtin_object_size(&foo.a, 3); // CHECK: store i32 4 gi = __builtin_object_size(&foo.b, 0); // CHECK: store i32 4 gi = __builtin_object_size(&foo.b, 1); // CHECK: store i32 4 gi = __builtin_object_size(&foo.b, 2); // CHECK: store i32 4 gi = __builtin_object_size(&foo.b, 3); } // CHECK-LABEL: @test20 void test20() { struct { int t[10]; } t[10]; // CHECK: store i32 380 gi = __builtin_object_size(&t[0].t[5], 0); // CHECK: store i32 20 gi = __builtin_object_size(&t[0].t[5], 1); // CHECK: store i32 380 gi = __builtin_object_size(&t[0].t[5], 2); // CHECK: store i32 20 gi = __builtin_object_size(&t[0].t[5], 3); } // CHECK-LABEL: @test21 void test21() { struct { int t; } t; // CHECK: store i32 0 gi = __builtin_object_size(&t + 1, 0); // CHECK: store i32 0 gi = __builtin_object_size(&t + 1, 1); // CHECK: store i32 0 gi = __builtin_object_size(&t + 1, 2); // CHECK: store i32 0 gi = __builtin_object_size(&t + 1, 3); // CHECK: store i32 0 gi = __builtin_object_size(&t.t + 1, 0); // CHECK: store i32 0 gi = __builtin_object_size(&t.t + 1, 1); // CHECK: store i32 0 gi = __builtin_object_size(&t.t + 1, 2); // CHECK: store i32 0 gi = __builtin_object_size(&t.t + 1, 3); } // CHECK-LABEL: @test22 void test22() { struct { int t[10]; } t[10]; // CHECK: store i32 0 gi = __builtin_object_size(&t[10], 0); // CHECK: store i32 0 gi = __builtin_object_size(&t[10], 1); // CHECK: store i32 0 gi = __builtin_object_size(&t[10], 2); // CHECK: store i32 0 gi = __builtin_object_size(&t[10], 3); // CHECK: store i32 0 gi = __builtin_object_size(&t[9].t[10], 0); // CHECK: store i32 0 gi = __builtin_object_size(&t[9].t[10], 1); // CHECK: store i32 0 gi = __builtin_object_size(&t[9].t[10], 2); // CHECK: store i32 0 gi = __builtin_object_size(&t[9].t[10], 3); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[0] + sizeof(t), 0); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[0] + sizeof(t), 1); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[0] + sizeof(t), 2); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[0] + sizeof(t), 3); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 0); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 1); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 2); // CHECK: store i32 0 gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 3); } struct Test23Ty { int a; int t[10]; }; // CHECK-LABEL: @test23 void test23(struct Test23Ty *p) { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(p, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(p, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(p, 2); // Note: this is currently fixed at 0 because LLVM doesn't have sufficient // data to correctly handle type=3 // CHECK: store i32 0 gi = __builtin_object_size(p, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(&p->a, 0); // CHECK: store i32 4 gi = __builtin_object_size(&p->a, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(&p->a, 2); // CHECK: store i32 4 gi = __builtin_object_size(&p->a, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(&p->t[5], 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(&p->t[5], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(&p->t[5], 2); // CHECK: store i32 20 gi = __builtin_object_size(&p->t[5], 3); } // PR24493 -- ICE if __builtin_object_size called with NULL and (Type & 1) != 0 // CHECK-LABEL: @test24 void test24() { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size((void*)0, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size((void*)0, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true) gi = __builtin_object_size((void*)0, 2); // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. // Hopefully will be lowered properly in the future. // CHECK: store i32 0 gi = __builtin_object_size((void*)0, 3); } // CHECK-LABEL: @test25 void test25() { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size((void*)0x1000, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size((void*)0x1000, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true) gi = __builtin_object_size((void*)0x1000, 2); // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. // Hopefully will be lowered properly in the future. // CHECK: store i32 0 gi = __builtin_object_size((void*)0x1000, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size((void*)0 + 0x1000, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size((void*)0 + 0x1000, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true) gi = __builtin_object_size((void*)0 + 0x1000, 2); // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. // Hopefully will be lowered properly in the future. // CHECK: store i32 0 gi = __builtin_object_size((void*)0 + 0x1000, 3); } // CHECK-LABEL: @test26 void test26() { struct { int v[10]; } t[10]; // CHECK: store i32 316 gi = __builtin_object_size(&t[1].v[11], 0); // CHECK: store i32 312 gi = __builtin_object_size(&t[1].v[12], 1); // CHECK: store i32 308 gi = __builtin_object_size(&t[1].v[13], 2); // CHECK: store i32 0 gi = __builtin_object_size(&t[1].v[14], 3); } struct Test27IncompleteTy; // CHECK-LABEL: @test27 void test27(struct Test27IncompleteTy *t) { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(t, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(t, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(t, 2); // Note: this is currently fixed at 0 because LLVM doesn't have sufficient // data to correctly handle type=3 // CHECK: store i32 0 gi = __builtin_object_size(t, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size(&test27, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) gi = __builtin_object_size(&test27, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 true) gi = __builtin_object_size(&test27, 2); // Note: this is currently fixed at 0 because LLVM doesn't have sufficient // data to correctly handle type=3 // CHECK: store i32 0 gi = __builtin_object_size(&test27, 3); } // The intent of this test is to ensure that __builtin_object_size treats `&foo` // and `(T*)&foo` identically, when used as the pointer argument. // CHECK-LABEL: @test28 void test28() { struct { int v[10]; } t[10]; #define addCasts(s) ((char*)((short*)(s))) // CHECK: store i32 360 gi = __builtin_object_size(addCasts(&t[1]), 0); // CHECK: store i32 360 gi = __builtin_object_size(addCasts(&t[1]), 1); // CHECK: store i32 360 gi = __builtin_object_size(addCasts(&t[1]), 2); // CHECK: store i32 360 gi = __builtin_object_size(addCasts(&t[1]), 3); // CHECK: store i32 356 gi = __builtin_object_size(addCasts(&t[1].v[1]), 0); // CHECK: store i32 36 gi = __builtin_object_size(addCasts(&t[1].v[1]), 1); // CHECK: store i32 356 gi = __builtin_object_size(addCasts(&t[1].v[1]), 2); // CHECK: store i32 36 gi = __builtin_object_size(addCasts(&t[1].v[1]), 3); #undef addCasts } struct DynStructVar { char fst[16]; char snd[]; }; struct DynStruct0 { char fst[16]; char snd[0]; }; struct DynStruct1 { char fst[16]; char snd[1]; }; struct StaticStruct { char fst[16]; char snd[2]; }; // CHECK-LABEL: @test29 void test29(struct DynStructVar *dv, struct DynStruct0 *d0, struct DynStruct1 *d1, struct StaticStruct *ss) { // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(dv->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(dv->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(dv->snd, 2); // CHECK: store i32 0 gi = __builtin_object_size(dv->snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(d0->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(d0->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(d0->snd, 2); // CHECK: store i32 0 gi = __builtin_object_size(d0->snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(d1->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(d1->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(d1->snd, 2); // CHECK: store i32 1 gi = __builtin_object_size(d1->snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(ss->snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(ss->snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(ss->snd, 2); // CHECK: store i32 2 gi = __builtin_object_size(ss->snd, 3); } // CHECK-LABEL: @test30 void test30() { struct { struct DynStruct1 fst, snd; } *nested; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(nested->fst.snd, 0); // CHECK: store i32 1 gi = __builtin_object_size(nested->fst.snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(nested->fst.snd, 2); // CHECK: store i32 1 gi = __builtin_object_size(nested->fst.snd, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(nested->snd.snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(nested->snd.snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(nested->snd.snd, 2); // CHECK: store i32 1 gi = __builtin_object_size(nested->snd.snd, 3); union { struct DynStruct1 d1; char c[1]; } *u; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(u->c, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(u->c, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(u->c, 2); // CHECK: store i32 1 gi = __builtin_object_size(u->c, 3); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(u->d1.snd, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(u->d1.snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(u->d1.snd, 2); // CHECK: store i32 1 gi = __builtin_object_size(u->d1.snd, 3); } // CHECK-LABEL: @test31 void test31() { // Miscellaneous 'writing off the end' detection tests struct DynStructVar *dsv; struct DynStruct0 *ds0; struct DynStruct1 *ds1; struct StaticStruct *ss; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(ds1[9].snd, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(&ss[9].snd[0], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(&ds1[9].snd[0], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(&ds0[9].snd[0], 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(&dsv[9].snd[0], 1); } // CHECK-LABEL: @PR30346 void PR30346() { struct sa_family_t {}; struct sockaddr { struct sa_family_t sa_family; char sa_data[14]; }; struct sockaddr *sa; // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(sa->sa_data, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false) gi = __builtin_object_size(sa->sa_data, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true) gi = __builtin_object_size(sa->sa_data, 2); // CHECK: store i32 14 gi = __builtin_object_size(sa->sa_data, 3); } extern char incomplete_char_array[]; // CHECK-LABEL: @incomplete_and_function_types int incomplete_and_function_types() { // CHECK: call i64 @llvm.objectsize.i64.p0i8 gi = __builtin_object_size(incomplete_char_array, 0); // CHECK: call i64 @llvm.objectsize.i64.p0i8 gi = __builtin_object_size(incomplete_char_array, 1); // CHECK: call i64 @llvm.objectsize.i64.p0i8 gi = __builtin_object_size(incomplete_char_array, 2); // CHECK: store i32 0 gi = __builtin_object_size(incomplete_char_array, 3); } + +// Flips between the pointer and lvalue evaluator a lot. +void deeply_nested() { + struct { + struct { + struct { + struct { + int e[2]; + char f; // Inhibit our writing-off-the-end check + } d[2]; + } c[2]; + } b[2]; + } *a; + + // CHECK: store i32 4 + gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 1); + // CHECK: store i32 4 + gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 3); +} Index: vendor/clang/dist/test/Parser/cxx1z-fold-expressions.cpp =================================================================== --- vendor/clang/dist/test/Parser/cxx1z-fold-expressions.cpp (revision 313882) +++ vendor/clang/dist/test/Parser/cxx1z-fold-expressions.cpp (revision 313883) @@ -1,36 +1,45 @@ // RUN: %clang_cc1 -std=c++1z -verify %s template constexpr auto sum(T ...t) { return (... + t); } template constexpr auto product(T ...t) { return (t * ...); } template constexpr auto all(T ...t) { return (true && ... && t); } template constexpr auto all2(T ...t) { return (t && ... && true); } int k1 = (1 + ... + 2); // expected-error {{does not contain any unexpanded parameter packs}} int k2 = (1 + ...); // expected-error {{does not contain any unexpanded parameter packs}} int k3 = (... + 2); // expected-error {{does not contain any unexpanded parameter packs}} struct A { A(int); friend A operator+(A, A); A operator-(A); A operator()(A); A operator[](A); }; A operator*(A, A); template void bad1() { (N + ... + N); } // expected-error {{unexpanded parameter packs in both operands}} // FIXME: it would be reasonable to support this as an extension. template void bad2() { (2 * N + ... + 1); } // expected-error {{expression not permitted as operand}} template void bad3() { (2 + N * ... * 1); } // expected-error {{expression not permitted as operand}} template void bad4(int (&...x)[N]) { (N + M * ... * 1); } // expected-error {{expression not permitted as operand}} template void fixed4(int (&...x)[N]) { ((N + M) * ... * 1); } template void bad4a(T ...t) { (t * 2 + ... + 1); } // expected-error {{expression not permitted as operand}} template void bad4b() { (A(0) + A(N) + ...); } // expected-error {{expression not permitted as operand}} template void bad4c() { (A(0) - A(N) + ...); } // expected-error {{expression not permitted as operand}} template void bad4d() { (A(0)(A(0)) + ... + A(0)[A(N)]); } // Parens are mandatory. template void bad5() { N + ...; } // expected-error {{expected expression}} expected-error +{{}} template void bad6() { ... + N; } // expected-error {{expected expression}} template void bad7() { N + ... + N; } // expected-error {{expected expression}} expected-error +{{}} // Must have a fold-operator in the relevant places. template int bad8() { return (N + ... * 3); } // expected-error {{operators in fold expression must be the same}} template int bad9() { return (3 + ... * N); } // expected-error {{operators in fold expression must be the same}} template int bad10() { return (3 ? ... : N); } // expected-error +{{}} expected-note {{to match}} template int bad11() { return (N + ... 0); } // expected-error {{expected a foldable binary operator}} expected-error {{expected expression}} template int bad12() { return (... N); } // expected-error {{expected expression}} + +template void as_operand_of_cast(int a, T ...t) { + return + (int)(a + ... + undeclared_junk) + // expected-error {{undeclared}} expected-error {{does not contain any unexpanded}} + (int)(t + ... + undeclared_junk) + // expected-error {{undeclared}} + (int)(... + undeclared_junk) + // expected-error {{undeclared}} expected-error {{does not contain any unexpanded}} + (int)(undeclared_junk + ...) + // expected-error {{undeclared}} + (int)(a + ...); // expected-error {{does not contain any unexpanded}} +} Index: vendor/clang/dist/test/Sema/builtin-object-size.c =================================================================== --- vendor/clang/dist/test/Sema/builtin-object-size.c (revision 313882) +++ vendor/clang/dist/test/Sema/builtin-object-size.c (revision 313883) @@ -1,78 +1,93 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin9 -verify %s int a[10]; int f0() { return __builtin_object_size(&a); // expected-error {{too few arguments to function}} } int f1() { return (__builtin_object_size(&a, 0) + __builtin_object_size(&a, 1) + __builtin_object_size(&a, 2) + __builtin_object_size(&a, 3)); } int f2() { return __builtin_object_size(&a, -1); // expected-error {{argument should be a value from 0 to 3}} } int f3() { return __builtin_object_size(&a, 4); // expected-error {{argument should be a value from 0 to 3}} } // rdar://6252231 - cannot call vsnprintf with va_list on x86_64 void f4(const char *fmt, ...) { __builtin_va_list args; __builtin___vsnprintf_chk (0, 42, 0, 11, fmt, args); // expected-warning {{'__builtin___vsnprintf_chk' will always overflow destination buffer}} } // rdar://18334276 typedef __typeof__(sizeof(int)) size_t; void * memcset(void *restrict dst, int src, size_t n); void * memcpy(void *restrict dst, const void *restrict src, size_t n); #define memset(dest, src, len) __builtin___memset_chk(dest, src, len, __builtin_object_size(dest, 0)) #define memcpy(dest, src, len) __builtin___memcpy_chk(dest, src, len, __builtin_object_size(dest, 0)) #define memcpy1(dest, src, len) __builtin___memcpy_chk(dest, src, len, __builtin_object_size(dest, 4)) #define NULL ((void *)0) void f5(void) { char buf[10]; memset((void *)0x100000000ULL, 0, 0x1000); memcpy((char *)NULL + 0x10000, buf, 0x10); memcpy1((char *)NULL + 0x10000, buf, 0x10); // expected-error {{argument should be a value from 0 to 3}} } // rdar://18431336 void f6(void) { char b[5]; char buf[10]; __builtin___memccpy_chk (buf, b, '\0', sizeof(b), __builtin_object_size (buf, 0)); __builtin___memccpy_chk (b, buf, '\0', sizeof(buf), __builtin_object_size (b, 0)); // expected-warning {{'__builtin___memccpy_chk' will always overflow destination buffer}} } int pr28314(void) { struct { struct InvalidField a; // expected-error{{has incomplete type}} expected-note 3{{forward declaration of 'struct InvalidField'}} char b[0]; } *p; struct { struct InvalidField a; // expected-error{{has incomplete type}} char b[1]; } *p2; struct { struct InvalidField a; // expected-error{{has incomplete type}} char b[2]; } *p3; int a = 0; a += __builtin_object_size(&p->a, 0); a += __builtin_object_size(p->b, 0); a += __builtin_object_size(p2->b, 0); a += __builtin_object_size(p3->b, 0); return a; } + +int pr31843() { + int n = 0; + + struct { int f; } a; + int b; + n += __builtin_object_size(({&(b ? &a : &a)->f; pr31843;}), 0); // expected-warning{{expression result unused}} + + struct statfs { char f_mntonname[1024];}; + struct statfs *outStatFSBuf; + n += __builtin_object_size(outStatFSBuf->f_mntonname ? "" : "", 1); // expected-warning{{address of array}} + n += __builtin_object_size(outStatFSBuf->f_mntonname ?: "", 1); + + return n; +} Index: vendor/clang/dist/test/SemaCXX/cxx11-inheriting-ctors.cpp =================================================================== --- vendor/clang/dist/test/SemaCXX/cxx11-inheriting-ctors.cpp (revision 313882) +++ vendor/clang/dist/test/SemaCXX/cxx11-inheriting-ctors.cpp (revision 313883) @@ -1,107 +1,135 @@ // RUN: %clang_cc1 -std=c++11 %s -verify namespace PR15757 { struct S { }; template struct T { template T(X x, A &&a) {} template explicit T(A &&a) noexcept(noexcept(T(X(), static_cast(a)))) : T(X(), static_cast(a)) {} }; template struct U : T { using T::T; }; U foo(char ch) { return U(ch); } int main() { U a(42); U b('4'); return 0; } } namespace WrongIdent { struct A {}; struct B : A {}; struct C : B { using B::A; }; } namespace DefaultCtorConflict { struct A { A(int = 0); }; struct B : A { using A::A; } b; // ok, not ambiguous, inherited constructor suppresses implicit default constructor struct C { B b; } c; } namespace InvalidConstruction { struct A { A(int); }; struct B { B() = delete; }; struct C : A, B { using A::A; }; // Initialization here is performed as if by a defaulted default constructor, // which would be ill-formed (in the immediate context) in this case because // it would be defined as deleted. template void f(decltype(T(0))*); template int &f(...); int &r = f(0); } namespace ExplicitConv { struct B {}; struct D : B { // expected-note 3{{candidate}} using B::B; }; struct X { explicit operator B(); } x; struct Y { explicit operator D(); } y; D dx(x); // expected-error {{no matching constructor}} D dy(y); } namespace NestedListInit { struct B { B(); } b; // expected-note 3{{candidate}} struct D : B { // expected-note 14{{not viable}} using B::B; }; // This is a bit weird. We're allowed one pair of braces for overload // resolution, and one more pair of braces due to [over.ics.list]/2. B b1 = {b}; B b2 = {{b}}; B b3 = {{{b}}}; // expected-error {{no match}} // Per a proposed defect resolution, we don't get to call // D's version of B::B(const B&) here. D d0 = b; // expected-error {{no viable conversion}} D d1 = {b}; // expected-error {{no match}} D d2 = {{b}}; // expected-error {{no match}} D d3 = {{{b}}}; // expected-error {{no match}} D d4 = {{{{b}}}}; // expected-error {{no match}} } namespace PR31606 { // PR31606: as part of a proposed defect resolution, do not consider // inherited constructors that would be copy constructors for any class // between the declaring class and the constructed class (inclusive). struct Base {}; struct A : Base { using Base::Base; bool operator==(A const &) const; // expected-note {{no known conversion from 'PR31606::B' to 'const PR31606::A' for 1st argument}} }; struct B : Base { using Base::Base; }; bool a = A{} == A{}; // Note, we do *not* allow operator=='s argument to use the inherited A::A(Base&&) constructor to construct from B{}. bool b = A{} == B{}; // expected-error {{invalid operands}} } + +namespace implicit_member_srcloc { + template + struct S3 { + }; + + template + struct S2 { + S2(S3 &&); + }; + + template + struct S1 : S2 { + using S2::S2; + S1(); + }; + + template + struct S0 { + S0(); + S0(S0&&) = default; + S1 m1; + }; + + void foo1() { + S0 s0; + } +} Index: vendor/clang/dist/test/SemaObjCXX/blocks.mm =================================================================== --- vendor/clang/dist/test/SemaObjCXX/blocks.mm (revision 313882) +++ vendor/clang/dist/test/SemaObjCXX/blocks.mm (revision 313883) @@ -1,146 +1,160 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class -std=c++11 %s @protocol NSObject; void bar(id(^)(void)); void foo(id (^objectCreationBlock)(void)) { return bar(objectCreationBlock); // OK } void bar2(id(*)(void)); void foo2(id (*objectCreationBlock)(void)) { return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)()' to parameter of type 'id (*)()'}} } void bar3(id(*)()); // expected-note{{candidate function}} void foo3(id (*objectCreationBlock)(int)) { return bar3(objectCreationBlock); // expected-error{{no matching}} } void bar4(id(^)()); // expected-note{{candidate function}} void foo4(id (^objectCreationBlock)(int)) { return bar4(objectCreationBlock); // expected-error{{no matching}} } void foo5(id (^x)(int)) { if (x) { } } // @interface Foo { @private void (^_block)(void); } - (void)bar; @end namespace N { class X { }; void foo(X); } @implementation Foo - (void)bar { _block(); foo(N::X()); // okay } @end typedef signed char BOOL; void foo6(void *block) { void (^vb)(id obj, int idx, BOOL *stop) = (void (^)(id, int, BOOL *))block; BOOL (^bb)(id obj, int idx, BOOL *stop) = (BOOL (^)(id, int, BOOL *))block; } // : Require that the types of block // parameters are complete. namespace N1 { template class ptr; // expected-note{{template is declared here}} template class foo { public: void bar(void (^)(ptr<_T>)); }; class X; void test2(); void test() { foo f; f.bar(^(ptr _f) { // expected-error{{implicit instantiation of undefined template 'N1::ptr'}} test2(); }); } } // Make sure we successfully instantiate the copy constructor of a // __block variable's type. namespace N2 { template struct A { A() {} A(const A &other) { int invalid[-n]; // expected-error 2 {{array with a negative size}} } }; void test1() { __block A<1> x; // expected-note {{requested here}} } template void test2() { __block A x; // expected-note {{requested here}} } template void test2<2>(); } // Handle value-dependent block declaration references. namespace N3 { template struct X { }; template void f() { X xN = ^() { return X(); }(); } } // rdar://8979379 @interface A @end @interface B : A @end void f(int (^bl)(A* a)); // expected-note {{candidate function not viable: no known conversion from 'int (^)(B *)' to 'int (^)(A *)' for 1st argument}} void g() { f(^(B* b) { return 0; }); // expected-error {{no matching function for call to 'f'}} } namespace DependentReturn { template void f(T t) { (void)^(T u) { if (t != u) return t + u; else return; }; (void)^(T u) { if (t == u) return; else return t + u; }; } struct X { }; void operator+(X, X); bool operator==(X, X); bool operator!=(X, X); template void f(X); +} + +namespace MoveBlockVariable { +struct B0 { +}; + +struct B1 { // expected-note 2 {{candidate constructor (the implicit}} + B1(B0&&); // expected-note {{candidate constructor not viable}} +}; + +B1 test_move() { + __block B0 b; + return b; // expected-error {{no viable conversion from returned value of type 'MoveBlockVariable::B0' to function return type 'MoveBlockVariable::B1'}} +} }