Vendor import of clang release_40 branch r295380:
https://llvm.org/svn/llvm-project/cfe/branches/release_40@295380
This commit is contained in:
parent
3bae525304
commit
eb2854521a
@ -2258,16 +2258,13 @@ 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
|
||||
|
@ -17,7 +17,7 @@ Written by the `LLVM Team <http://llvm.org/>`_
|
||||
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
|
||||
@ -139,7 +139,76 @@ 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
|
||||
<https://clang.llvm.org/docs/UsersManual.html#opencl-features>`_ to Clang
|
||||
documentation.
|
||||
|
||||
OpenMP Support in Clang
|
||||
----------------------------------
|
||||
|
@ -2056,6 +2056,8 @@ can be given manually.
|
||||
In this case the kernel code should contain ``#include <opencl-c.h>`` just as a
|
||||
regular C include.
|
||||
|
||||
.. _opencl_cl_ext:
|
||||
|
||||
.. option:: -cl-ext
|
||||
|
||||
Disables support of OpenCL extensions. All OpenCL targets provide a list
|
||||
@ -2177,6 +2179,41 @@ To enable modules for OpenCL:
|
||||
|
||||
$ clang -target spir-unknown-unknown -c -emit-llvm -Xclang -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=<path to the generated module> test.cl
|
||||
|
||||
OpenCL Extensions
|
||||
-----------------
|
||||
|
||||
All of the ``cl_khr_*`` extensions from `the official OpenCL specification
|
||||
<https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/EXTENSION.html>`_
|
||||
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 <opencl_cl_ext>` 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
|
||||
---------------
|
||||
|
||||
@ -2215,7 +2252,7 @@ does not have any effect on the IR. For more details reffer to the specification
|
||||
<https://www.khronos.org/registry/cl/specs/opencl-2.0-openclc.pdf#49>`_
|
||||
|
||||
|
||||
opencl_hint_unroll
|
||||
opencl_unroll_hint
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The implementation of this feature mirrors the unroll hint for C.
|
||||
|
@ -604,10 +604,12 @@ namespace {
|
||||
/// 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
|
||||
@ -890,10 +892,6 @@ namespace {
|
||||
return KeepGoing;
|
||||
}
|
||||
|
||||
bool allowInvalidBaseExpr() const {
|
||||
return EvalMode == EM_OffsetFold;
|
||||
}
|
||||
|
||||
class ArrayInitLoopIndex {
|
||||
EvalInfo &Info;
|
||||
uint64_t OuterIndex;
|
||||
@ -1394,8 +1392,10 @@ 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);
|
||||
@ -4803,6 +4803,7 @@ class LValueExprEvaluatorBase
|
||||
: public ExprEvaluatorBase<Derived> {
|
||||
protected:
|
||||
LValue &Result;
|
||||
bool InvalidBaseOK;
|
||||
typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy;
|
||||
typedef ExprEvaluatorBase<Derived> ExprEvaluatorBaseTy;
|
||||
|
||||
@ -4811,9 +4812,14 @@ protected:
|
||||
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);
|
||||
@ -4825,7 +4831,7 @@ public:
|
||||
QualType BaseTy;
|
||||
bool EvalOK;
|
||||
if (E->isArrow()) {
|
||||
EvalOK = EvaluatePointer(E->getBase(), Result, this->Info);
|
||||
EvalOK = evaluatePointer(E->getBase(), Result);
|
||||
BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType();
|
||||
} else if (E->getBase()->isRValue()) {
|
||||
assert(E->getBase()->getType()->isRecordType());
|
||||
@ -4836,7 +4842,7 @@ public:
|
||||
BaseTy = E->getBase()->getType();
|
||||
}
|
||||
if (!EvalOK) {
|
||||
if (!this->Info.allowInvalidBaseExpr())
|
||||
if (!InvalidBaseOK)
|
||||
return false;
|
||||
Result.setInvalid(E);
|
||||
return true;
|
||||
@ -4930,8 +4936,8 @@ namespace {
|
||||
class LValueExprEvaluator
|
||||
: public LValueExprEvaluatorBase<LValueExprEvaluator> {
|
||||
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);
|
||||
@ -4984,10 +4990,11 @@ public:
|
||||
/// * 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<ObjCSelectorExpr>(E));
|
||||
return LValueExprEvaluator(Info, Result).Visit(E);
|
||||
return LValueExprEvaluator(Info, Result, InvalidBaseOK).Visit(E);
|
||||
}
|
||||
|
||||
bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
|
||||
@ -5148,7 +5155,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
|
||||
if (E->getBase()->getType()->isVectorType())
|
||||
return Error(E);
|
||||
|
||||
if (!EvaluatePointer(E->getBase(), Result, Info))
|
||||
if (!evaluatePointer(E->getBase(), Result))
|
||||
return false;
|
||||
|
||||
APSInt Index;
|
||||
@ -5160,7 +5167,7 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
|
||||
}
|
||||
|
||||
bool LValueExprEvaluator::VisitUnaryDeref(const UnaryOperator *E) {
|
||||
return EvaluatePointer(E->getSubExpr(), Result, Info);
|
||||
return evaluatePointer(E->getSubExpr(), Result);
|
||||
}
|
||||
|
||||
bool LValueExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
|
||||
@ -5308,7 +5315,7 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
|
||||
/// 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.
|
||||
@ -5342,17 +5349,27 @@ namespace {
|
||||
class PointerExprEvaluator
|
||||
: public ExprEvaluatorBase<PointerExprEvaluator> {
|
||||
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);
|
||||
@ -5399,9 +5416,10 @@ public:
|
||||
};
|
||||
} // 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) {
|
||||
@ -5414,7 +5432,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
|
||||
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;
|
||||
|
||||
@ -5432,7 +5450,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
|
||||
}
|
||||
|
||||
bool PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
|
||||
return EvaluateLValue(E->getSubExpr(), Result, Info);
|
||||
return evaluateLValue(E->getSubExpr(), Result);
|
||||
}
|
||||
|
||||
bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
||||
@ -5466,7 +5484,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
||||
|
||||
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;
|
||||
@ -5513,7 +5531,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
||||
}
|
||||
case CK_ArrayToPointerDecay:
|
||||
if (SubExpr->isGLValue()) {
|
||||
if (!EvaluateLValue(SubExpr, Result, Info))
|
||||
if (!evaluateLValue(SubExpr, Result))
|
||||
return false;
|
||||
} else {
|
||||
Result.set(SubExpr, Info.CurrentCall->Index);
|
||||
@ -5530,18 +5548,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -5586,7 +5605,7 @@ 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);
|
||||
@ -5609,12 +5628,12 @@ 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);
|
||||
@ -6255,7 +6274,7 @@ class TemporaryExprEvaluator
|
||||
: public LValueExprEvaluatorBase<TemporaryExprEvaluator> {
|
||||
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) {
|
||||
@ -7358,7 +7377,8 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ struct ObjCEntrypoints {
|
||||
/// 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);
|
||||
|
@ -2408,7 +2408,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
||||
// 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(),
|
||||
|
@ -2831,6 +2831,9 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
|
||||
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);
|
||||
@ -2912,7 +2915,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
|
||||
VK = VK_RValue;
|
||||
}
|
||||
|
||||
OpaqueValueExpr FakeArg(SourceLocation(), ArgType, VK);
|
||||
OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK);
|
||||
|
||||
if (SM != CXXDefaultConstructor) {
|
||||
NumArgs = 1;
|
||||
@ -2926,13 +2929,13 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
|
||||
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()) {
|
||||
@ -2987,7 +2990,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD,
|
||||
}
|
||||
|
||||
OverloadCandidateSet::iterator Best;
|
||||
switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) {
|
||||
switch (OCS.BestViableFunction(*this, LookupLoc, Best)) {
|
||||
case OR_Success:
|
||||
Result->setMethod(cast<CXXMethodDecl>(Best->Function));
|
||||
Result->setKind(SpecialMemberOverloadResult::Success);
|
||||
|
@ -2743,15 +2743,17 @@ bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
|
||||
// ...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<BlocksAttr>()) 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<BlocksAttr>()) return false;
|
||||
|
||||
// Variables with higher required alignment than their type's ABI
|
||||
// alignment cannot use NRVO.
|
||||
if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() &&
|
||||
|
@ -1014,6 +1014,11 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
|
||||
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
|
||||
@ -1021,6 +1026,7 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
|
||||
if (LHS && RHS &&
|
||||
LHS->containsUnexpandedParameterPack() ==
|
||||
RHS->containsUnexpandedParameterPack()) {
|
||||
DiscardOperands();
|
||||
return Diag(EllipsisLoc,
|
||||
LHS->containsUnexpandedParameterPack()
|
||||
? diag::err_fold_expression_packs_both_sides
|
||||
@ -1034,6 +1040,7 @@ ExprResult Sema::ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
|
||||
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();
|
||||
|
@ -549,3 +549,22 @@ int incomplete_and_function_types() {
|
||||
// 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);
|
||||
}
|
||||
|
@ -34,3 +34,12 @@ template<int ...N> int bad9() { return (3 + ... * N); } // expected-error {{oper
|
||||
template<int ...N> int bad10() { return (3 ? ... : N); } // expected-error +{{}} expected-note {{to match}}
|
||||
template<int ...N> int bad11() { return (N + ... 0); } // expected-error {{expected a foldable binary operator}} expected-error {{expected expression}}
|
||||
template<int ...N> int bad12() { return (... N); } // expected-error {{expected expression}}
|
||||
|
||||
template<typename ...T> 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}}
|
||||
}
|
||||
|
@ -76,3 +76,18 @@ int pr28314(void) {
|
||||
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;
|
||||
}
|
||||
|
@ -105,3 +105,31 @@ namespace PR31606 {
|
||||
// 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<class T>
|
||||
struct S3 {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct S2 {
|
||||
S2(S3<T> &&);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct S1 : S2<T> {
|
||||
using S2<T>::S2;
|
||||
S1();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct S0 {
|
||||
S0();
|
||||
S0(S0&&) = default;
|
||||
S1<T> m1;
|
||||
};
|
||||
|
||||
void foo1() {
|
||||
S0<int> s0;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 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));
|
||||
@ -144,3 +144,17 @@ namespace DependentReturn {
|
||||
|
||||
template void f<X>(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'}}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user