summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/Attr.td9
-rw-r--r--clang/include/clang/Basic/AttrDocs.td38
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--clang/lib/AST/ExprConstant.cpp616
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp24
-rw-r--r--clang/lib/CodeGen/CGCall.cpp8
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h4
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h14
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp88
-rw-r--r--clang/test/CodeGen/alloc-size.c352
-rw-r--r--clang/test/CodeGenCXX/alloc-size.cpp72
-rw-r--r--clang/test/CodeGenCXX/block-in-ctor-dtor.cpp2
-rw-r--r--clang/test/CodeGenCXX/global-init.cpp3
-rw-r--r--clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl24
-rw-r--r--clang/test/Sema/alloc-size.c23
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx11.cpp4
16 files changed, 205 insertions, 1079 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index f6a5e54b2b3..4c8276a553f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -780,15 +780,6 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Documentation = [EmptyBasesDocs];
}
-def AllocSize : InheritableAttr {
- let Spellings = [GCC<"alloc_size">];
- let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
- "ExpectedFunctionWithProtoType">;
- let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam", 1>];
- let TemplateDependent = 1;
- let Documentation = [AllocSizeDocs];
-}
-
def EnableIf : InheritableAttr {
let Spellings = [GNU<"enable_if">];
let Subjects = SubjectList<[Function]>;
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index b57833a15f3..5502af2a585 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -206,44 +206,6 @@ to enforce the provided alignment assumption.
}];
}
-def AllocSizeDocs : Documentation {
- let Category = DocCatFunction;
- let Content = [{
-The ``alloc_size`` attribute can be placed on functions that return pointers in
-order to hint to the compiler how many bytes of memory will be available at the
-returned poiner. ``alloc_size`` takes one or two arguments.
-
-- ``alloc_size(N)`` implies that argument number N equals the number of
- available bytes at the returned pointer.
-- ``alloc_size(N, M)`` implies that the product of argument number N and
- argument number M equals the number of available bytes at the returned
- pointer.
-
-Argument numbers are 1-based.
-
-An example of how to use ``alloc_size``
-
-.. code-block:: c
-
- void *my_malloc(int a) __attribute__((alloc_size(1)));
- void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2)));
-
- int main() {
- void *const p = my_malloc(100);
- assert(__builtin_object_size(p, 0) == 100);
- void *const a = my_calloc(20, 5);
- assert(__builtin_object_size(a, 0) == 100);
- }
-
-.. Note:: This attribute works differently in clang than it does in GCC.
- Specifically, clang will only trace ``const`` pointers (as above); we give up
- on pointers that are not marked as ``const``. In the vast majority of cases,
- this is unimportant, because LLVM has support for the ``alloc_size``
- attribute. However, this may cause mildly unintuitive behavior when used with
- other attributes, such as ``enable_if``.
- }];
-}
-
def EnableIfDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 068f9de6733..69322f0f75b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2297,9 +2297,6 @@ def warn_attribute_pointers_only : Warning<
"%0 attribute only applies to%select{| constant}1 pointer arguments">,
InGroup<IgnoredAttributes>;
def err_attribute_pointers_only : Error<warn_attribute_pointers_only.Text>;
-def err_attribute_integers_only : Error<
- "%0 attribute argument may only refer to a function parameter of integer "
- "type">;
def warn_attribute_return_pointers_only : Warning<
"%0 attribute only applies to return values that are pointers">,
InGroup<IgnoredAttributes>;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 63cd5df94e0..0abdaa879ec 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -109,57 +109,19 @@ namespace {
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<AllocSizeAttr>() : 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<CastExpr>(E))
- E = Cast->getSubExpr()->IgnoreParens();
-
- if (const auto *CE = dyn_cast<CallExpr>(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<const Expr *>();
- 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<APValue::LValuePathEntry> 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");
+ static
+ unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base,
+ ArrayRef<APValue::LValuePathEntry> Path,
+ uint64_t &ArraySize, QualType &Type,
+ bool &IsArray) {
unsigned MostDerivedLength = 0;
- Type = getType(Base);
-
+ Type = Base;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
if (Type->isArrayType()) {
const ConstantArrayType *CAT =
- cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
+ cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
Type = CAT->getElementType();
ArraySize = CAT->getSize().getZExtValue();
MostDerivedLength = I + 1;
@@ -200,23 +162,17 @@ namespace {
/// Is this a pointer one past the end of an object?
unsigned IsOnePastTheEnd : 1;
- /// Indicator of whether the first entry is an unsized array.
- bool 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;
+ unsigned MostDerivedPathLength : 29;
/// 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.
@@ -231,24 +187,23 @@ namespace {
explicit SubobjectDesignator(QualType T)
: Invalid(false), IsOnePastTheEnd(false),
- FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false),
- MostDerivedPathLength(0), MostDerivedArraySize(0),
- MostDerivedType(T) {}
+ 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?");
+ MostDerivedIsArrayElement(false), MostDerivedPathLength(0),
+ MostDerivedArraySize(0) {
if (!Invalid) {
IsOnePastTheEnd = V.isLValueOnePastTheEnd();
ArrayRef<PathEntry> 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);
+ MostDerivedPathLength =
+ findMostDerivedSubobject(Ctx, getType(V.getLValueBase()),
+ V.getLValuePath(), MostDerivedArraySize,
+ MostDerivedType, IsArray);
MostDerivedIsArrayElement = IsArray;
}
}
@@ -259,25 +214,12 @@ namespace {
Entries.clear();
}
- /// Determine whether the most derived subobject is an array without a
- /// known bound.
- bool isMostDerivedAnUnsizedArray() const {
- return FirstEntryIsAnUnsizedArray && Entries.size() == 1;
- }
-
- /// 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 &&
+ if (MostDerivedIsArrayElement &&
Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize)
return true;
return false;
@@ -305,21 +247,6 @@ namespace {
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<uint64_t>::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) {
@@ -353,16 +280,10 @@ namespace {
/// 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()) {
+ if (Entries.back().ArrayIndex > MostDerivedArraySize) {
diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex);
setInvalid();
}
@@ -603,15 +524,9 @@ 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.
- /// 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,
+ /// Evaluate as a constant expression. Continue evaluating if we find a
+ /// MemberExpr with a base that can't be evaluated.
+ EM_DesignatorFold,
} EvalMode;
/// Are we checking whether the expression is a potential constant
@@ -713,7 +628,7 @@ namespace {
case EM_PotentialConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_PotentialConstantExpressionUnevaluated:
- case EM_OffsetFold:
+ case EM_DesignatorFold:
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -805,7 +720,7 @@ namespace {
case EM_ConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
- case EM_OffsetFold:
+ case EM_DesignatorFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -824,7 +739,7 @@ namespace {
case EM_EvaluateForOverflow:
case EM_IgnoreSideEffects:
case EM_ConstantFold:
- case EM_OffsetFold:
+ case EM_DesignatorFold:
return true;
case EM_PotentialConstantExpression:
@@ -860,7 +775,7 @@ namespace {
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
case EM_IgnoreSideEffects:
- case EM_OffsetFold:
+ case EM_DesignatorFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -890,7 +805,7 @@ namespace {
}
bool allowInvalidBaseExpr() const {
- return EvalMode == EM_OffsetFold;
+ return EvalMode == EM_DesignatorFold;
}
class ArrayInitLoopIndex {
@@ -941,10 +856,11 @@ namespace {
struct FoldOffsetRAII {
EvalInfo &Info;
EvalInfo::EvaluationMode OldMode;
- explicit FoldOffsetRAII(EvalInfo &Info)
+ explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject)
: Info(Info), OldMode(Info.EvalMode) {
if (!Info.checkingPotentialConstantExpression())
- Info.EvalMode = EvalInfo::EM_OffsetFold;
+ Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold
+ : EvalInfo::EM_ConstantFold;
}
~FoldOffsetRAII() { Info.EvalMode = OldMode; }
@@ -1050,12 +966,10 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E,
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<int>(N) << /*array*/ 0
- << static_cast<unsigned>(getMostDerivedArraySize());
+ << static_cast<unsigned>(MostDerivedArraySize);
else
Info.CCEDiag(E, diag::note_constexpr_array_index)
<< static_cast<int>(N) << /*non-array*/ 1;
@@ -1188,16 +1102,12 @@ namespace {
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?");
+ else
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?");
+ assert(V.isLValue());
Base = V.getLValueBase();
Offset = V.getLValueOffset();
InvalidBase = false;
@@ -1208,15 +1118,6 @@ namespace {
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<const Expr *>();
- assert((isa<MemberExpr>(E) || tryUnwrapAllocSizeCall(E)) &&
- "Unexpected type of invalid base");
- }
-#endif
-
Base = B;
Offset = CharUnits::fromQuantity(Offset_);
InvalidBase = BInvalid;
@@ -1256,13 +1157,6 @@ namespace {
if (checkSubobject(Info, E, isa<FieldDecl>(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);
@@ -2902,7 +2796,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// All the remaining cases only permit reading.
Info.FFDiag(E, diag::note_constexpr_modify_global);
return CompleteObject();
- } else if (VD->isConstexpr() || BaseType.isConstQualified()) {
+ } 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.
@@ -5185,105 +5079,6 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
// 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 Expr *>();
- 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())
- 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<VarDecl>(Base.dyn_cast<const ValueDecl *>());
- 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<PointerType>()->getPointeeType();
- Result.addUnsizedArray(Info, Pointee);
- return true;
-}
-
namespace {
class PointerExprEvaluator
: public ExprEvaluatorBase<PointerExprEvaluator> {
@@ -5293,8 +5088,6 @@ class PointerExprEvaluator
Result.set(E);
return true;
}
-
- bool visitNonBuiltinCallExpr(const CallExpr *E);
public:
PointerExprEvaluator(EvalInfo &info, LValue &Result)
@@ -5477,19 +5270,6 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
case CK_FunctionToPointerDecay:
return EvaluateLValue(SubExpr, Result, Info);
-
- 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 evaluateLValueAsAllocSize(Info, LVal.Base, Result);
- return Success(RVal, E);
- }
}
return ExprEvaluatorBaseTy::VisitCastExpr(E);
@@ -5527,20 +5307,6 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) {
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)))
- return false;
-
- Result.setInvalid(E);
- QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType();
- Result.addUnsizedArray(Info, PointeeTy);
- return true;
-}
-
bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (IsStringLiteralCall(E))
return Success(E);
@@ -5548,7 +5314,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (unsigned BuiltinOp = E->getBuiltinCallee())
return VisitBuiltinCallExpr(E, BuiltinOp);
- return visitNonBuiltinCallExpr(E);
+ return ExprEvaluatorBaseTy::VisitCallExpr(E);
}
bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
@@ -5707,7 +5473,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
}
default:
- return visitNonBuiltinCallExpr(E);
+ return ExprEvaluatorBaseTy::VisitCallExpr(E);
}
}
@@ -6746,6 +6512,8 @@ public:
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
+private:
+ bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type);
// FIXME: Missing: array subscript of vector, member of vector
};
} // end anonymous namespace
@@ -7017,7 +6785,7 @@ static QualType getObjectType(APValue::LValueBase B) {
}
/// A more selective version of E->IgnoreParenCasts for
-/// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only
+/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only
/// to change the type of E.
/// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo`
///
@@ -7084,51 +6852,39 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
}
}
- 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<PointerType>()->getPointeeType();
- }
-
- for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) {
- const auto &Entry = LVal.Designator.Entries[I];
+ for (int I = 0, E = LVal.Designator.Entries.size(); I != E; ++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<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
- uint64_t Index = Entry.ArrayIndex;
+ auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
+ uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
if (Index + 1 != CAT->getSize())
return false;
BaseType = CAT->getElementType();
} else if (BaseType->isAnyComplexType()) {
- const auto *CT = BaseType->castAs<ComplexType>();
- uint64_t Index = Entry.ArrayIndex;
+ auto *CT = BaseType->castAs<ComplexType>();
+ uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
if (Index != 1)
return false;
BaseType = CT->getElementType();
- } else if (auto *FD = getAsField(Entry)) {
+ } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) {
bool Invalid;
if (!IsLastOrInvalidFieldDecl(FD, Invalid))
return Invalid;
BaseType = FD->getType();
} else {
- assert(getAsBaseClass(Entry) && "Expecting cast to a base class");
+ assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr &&
+ "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].
+/// Tests to see if the LValue has a designator (that isn't necessarily valid).
static bool refersToCompleteObject(const LValue &LVal) {
if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty())
return false;
@@ -7136,142 +6892,42 @@ static bool refersToCompleteObject(const LValue &LVal) {
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<const Expr *>();
- return !E || !isa<MemberExpr>(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<CharUnits::QuantityType>::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) {
- // __builtin_object_size(&foo, N) == __builtin_object_size(&foo, (N & ~1U)).
- // (Where foo is an expression that has no designator). Hence, if we've no
- // designator, we can ignore the subobject bit.
- bool EvaluateAsCompleteObject =
- !(Type & 1) || LVal.Designator.isMostDerivedAnUnsizedArray() ||
- refersToCompleteObject(LVal);
-
- // 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 (LVal.Designator.Invalid || EvaluateAsCompleteObject) {
- // We can't give a correct lower bound for Type=3 if the designator is
- // invalid and we're meant to be evaluating it.
- if (Type == 3 && LVal.Designator.Invalid && !EvaluateAsCompleteObject)
- 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 !BaseTy.isNull() && HandleSizeof(Info, ExprLoc, 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 (!HandleSizeof(Info, ExprLoc, 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;
+ auto *E = LVal.Base.dyn_cast<const Expr *>();
+ (void)E;
+ assert(E != nullptr && isa<MemberExpr>(E));
+ return false;
}
-/// \brief Tries to evaluate the __builtin_object_size for @p E. If successful,
-/// returns true and stores the result in @p Size.
+/// 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) {
+ EvalInfo &Info, uint64_t &Size,
+ bool *WasError = nullptr) {
+ if (WasError != nullptr)
+ *WasError = false;
+
+ auto Error = [&](const Expr *E) {
+ if (WasError != nullptr)
+ *WasError = true;
+ return false;
+ };
+
+ auto Success = [&](uint64_t S, const Expr *E) {
+ Size = S;
+ return true;
+ };
+
// Determine the denoted object.
- LValue LVal;
+ LValue Base;
{
// 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);
+ FoldOffsetRAII Fold(Info, Type & 1);
if (E->isGLValue()) {
// It's possible for us to be given GLValues if we're called via
@@ -7279,29 +6935,122 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
APValue RVal;
if (!EvaluateAsRValue(Info, E, RVal))
return false;
- LVal.setFrom(Info.Ctx, RVal);
- } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info))
+ Base.setFrom(Info.Ctx, RVal);
+ } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), Base, Info))
return false;
}
+ CharUnits BaseOffset = Base.getLValueOffset();
// If we point to before the start of the object, there are no accessible
// bytes.
- if (LVal.getLValueOffset().isNegative()) {
- Size = 0;
- return true;
+ if (BaseOffset.isNegative())
+ return Success(0, E);
+
+ // In the case where we're not dealing with a subobject, we discard the
+ // subobject bit.
+ bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base);
+
+ // If Type & 1 is 0, we need to be able to statically guarantee that the bytes
+ // exist. If we can't verify the base, then we can't do that.
+ //
+ // As a special case, we produce a valid object size for an unknown object
+ // with a known designator if Type & 1 is 1. For instance:
+ //
+ // extern struct X { char buff[32]; int a, b, c; } *p;
+ // int a = __builtin_object_size(p->buff + 4, 3); // returns 28
+ // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40
+ //
+ // This matches GCC's behavior.
+ if (Base.InvalidBase && !SubobjectOnly)
+ return Error(E);
+
+ // If we're not examining only the subobject, then we reset to a complete
+ // object designator
+ //
+ // If Type is 1 and we've lost track of the subobject, just find the complete
+ // object instead. (If Type is 3, that's not correct behavior and we should
+ // return 0 instead.)
+ LValue End = Base;
+ if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) {
+ QualType T = getObjectType(End.getLValueBase());
+ if (T.isNull())
+ End.Designator.setInvalid();
+ else {
+ End.Designator = SubobjectDesignator(T);
+ End.Offset = CharUnits::Zero();
+ }
}
- CharUnits EndOffset;
- if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset))
+ // If it is not possible to determine which objects ptr points to at compile
+ // time, __builtin_object_size should return (size_t) -1 for type 0 or 1
+ // and (size_t) 0 for type 2 or 3.
+ if (End.Designator.Invalid)
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;
+ // 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 AmountToAdd = 1;
+ if (End.Designator.MostDerivedIsArrayElement &&
+ End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) {
+ // We got a pointer to an array. Step to its end.
+ AmountToAdd = End.Designator.MostDerivedArraySize -
+ End.Designator.Entries.back().ArrayIndex;
+ } else if (End.Designator.isOnePastTheEnd()) {
+ // We're already pointing at the end of the object.
+ AmountToAdd = 0;
+ }
+
+ QualType PointeeType = End.Designator.MostDerivedType;
+ assert(!PointeeType.isNull());
+ if (PointeeType->isIncompleteType() || PointeeType->isFunctionType())
+ return Error(E);
+
+ if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType,
+ AmountToAdd))
+ return false;
+
+ auto EndOffset = End.getLValueOffset();
+
+ // 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);
+ //
+ // So, if we see that we're examining an array at the end of a struct with an
+ // unknown base, we give up instead of breaking code that behaves this way.
+ // Note that we only do this when Type=1, because Type=3 is a lower bound, so
+ // answering conservatively is fine.
+ //
+ // 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.
+ if (End.InvalidBase && SubobjectOnly && Type == 1 &&
+ End.Designator.Entries.size() == End.Designator.MostDerivedPathLength &&
+ End.Designator.MostDerivedIsArrayElement &&
+ isDesignatorAtObjectEnd(Info.Ctx, End))
+ return false;
+
+ if (BaseOffset > EndOffset)
+ return Success(0, E);
+
+ return Success((EndOffset - BaseOffset).getQuantity(), E);
+}
+
+bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E,
+ unsigned Type) {
+ uint64_t Size;
+ bool WasError;
+ if (::tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size, &WasError))
+ return Success(Size, E);
+ if (WasError)
+ return Error(E);
+ return false;
}
bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
@@ -7323,9 +7072,8 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
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 (TryEvaluateBuiltinObjectSize(E, Type))
+ return true;
if (E->getArg(0)->HasSideEffects(Info.Ctx))
return Success((Type & 2) ? 0 : -1, E);
@@ -7338,7 +7086,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case EvalInfo::EM_ConstantFold:
case EvalInfo::EM_EvaluateForOverflow:
case EvalInfo::EM_IgnoreSideEffects:
- case EvalInfo::EM_OffsetFold:
+ case EvalInfo::EM_DesignatorFold:
// Leave it to IR generation.
return Error(E);
case EvalInfo::EM_ConstantExpressionUnevaluated:
@@ -10441,5 +10189,5 @@ bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
- return tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
+ return ::tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
}
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index b250b9a32b1..50a6d61e7e5 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -686,8 +686,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
// If the block has no captures, we won't have a pre-computed
// layout for it.
if (!blockExpr->getBlockDecl()->hasCaptures()) {
- if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr))
- return Block;
CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
computeBlockInfo(CGM, this, blockInfo);
blockInfo.BlockExpression = blockExpr;
@@ -1049,19 +1047,9 @@ Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
return addr;
}
-void CodeGenModule::setAddrOfGlobalBlock(const BlockExpr *BE,
- llvm::Constant *Addr) {
- bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second;
- (void)Ok;
- assert(Ok && "Trying to replace an already-existing global block!");
-}
-
llvm::Constant *
CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE,
StringRef Name) {
- if (llvm::Constant *Block = getAddrOfGlobalBlockIfEmitted(BE))
- return Block;
-
CGBlockInfo blockInfo(BE->getBlockDecl(), Name);
blockInfo.BlockExpression = BE;
@@ -1086,11 +1074,6 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
const CGBlockInfo &blockInfo,
llvm::Constant *blockFn) {
assert(blockInfo.CanBeGlobal);
- // Callers should detect this case on their own: calling this function
- // generally requires computing layout information, which is a waste of time
- // if we've already emitted this block.
- assert(!CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression) &&
- "Refusing to re-emit a global block.");
// Generate the constants for the block literal initializer.
ConstantInitBuilder builder(CGM);
@@ -1120,12 +1103,9 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
/*constant*/ true);
// Return a constant of the appropriately-casted type.
- llvm::Type *RequiredType =
+ llvm::Type *requiredType =
CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType());
- llvm::Constant *Result =
- llvm::ConstantExpr::getBitCast(literal, RequiredType);
- CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result);
- return Result;
+ return llvm::ConstantExpr::getBitCast(literal, requiredType);
}
void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 9b96a59aec3..02cbdf0c9e8 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1683,14 +1683,6 @@ void CodeGenModule::ConstructAttributeList(
HasAnyX86InterruptAttr = TargetDecl->hasAttr<AnyX86InterruptAttr>();
HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
- if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
- Optional<unsigned> NumElemsParam;
- // alloc_size args are base-1, 0 means not present.
- if (unsigned N = AllocSize->getNumElemsParam())
- NumElemsParam = N - 1;
- FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam() - 1,
- NumElemsParam);
- }
}
// OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index b78abdc1112..7d21e5cb978 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1499,6 +1499,7 @@ public:
//===--------------------------------------------------------------------===//
llvm::Value *EmitBlockLiteral(const BlockExpr *);
+ llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
static void destroyBlockInfos(CGBlockInfo *info);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
@@ -2725,9 +2726,6 @@ public:
OMPPrivateScope &LoopScope);
private:
- /// Helpers for blocks
- llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
-
/// Helpers for the OpenMP loop directives.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit);
void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 5f06ba90cf1..f26c92d5670 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -455,10 +455,6 @@ private:
bool isTriviallyRecursive(const FunctionDecl *F);
bool shouldEmitFunction(GlobalDecl GD);
- /// 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<const BlockExpr *, llvm::Constant *> EmittedGlobalBlocks;
-
/// @name Cache for Blocks Runtime Globals
/// @{
@@ -780,16 +776,6 @@ public:
/// 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);
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 114f684c420..2ecea5fd697 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -246,28 +246,6 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
return true;
}
-/// \brief Wrapper around checkUInt32Argument, with an extra check to be sure
-/// that the result will fit into a regular (signed) int. All args have the same
-/// purpose as they do in checkUInt32Argument.
-static bool checkPositiveIntArgument(Sema &S, const AttributeList &Attr,
- const Expr *Expr, int &Val,
- unsigned Idx = UINT_MAX) {
- uint32_t UVal;
- if (!checkUInt32Argument(S, Attr, Expr, UVal, Idx))
- return false;
-
- if (UVal > std::numeric_limits<int>::max()) {
- llvm::APSInt I(32); // for toString
- I = UVal;
- S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
- << I.toString(10, false) << 32 << /* Unsigned */ 0;
- return false;
- }
-
- Val = UVal;
- return true;
-}
-
/// \brief Diagnose mutually exclusive attributes when present on a given
/// declaration. Returns true if diagnosed.
template <typename AttrTy>
@@ -752,69 +730,6 @@ static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
-/// \brief Checks to be sure that the given parameter number is inbounds, and is
-/// an some integral type. Will emit appropriate diagnostics if this returns
-/// false.
-///
-/// FuncParamNo is expected to be from the user, so is base-1. AttrArgNo is used
-/// to actually retrieve the argument, so it's base-0.
-static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
- const AttributeList &Attr,
- unsigned FuncParamNo, unsigned AttrArgNo) {
- assert(Attr.isArgExpr(AttrArgNo) && "Expected expression argument");
- uint64_t Idx;
- if (!checkFunctionOrMethodParameterIndex(S, FD, Attr, FuncParamNo,
- Attr.getArgAsExpr(AttrArgNo), Idx))
- return false;
-
- const ParmVarDecl *Param = FD->getParamDecl(Idx);
- if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) {
- SourceLocation SrcLoc = Attr.getArgAsExpr(AttrArgNo)->getLocStart();
- S.Diag(SrcLoc, diag::err_attribute_integers_only)
- << Attr.getName() << Param->getSourceRange();
- return false;
- }
- return true;
-}
-
-static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- if (!checkAttributeAtLeastNumArgs(S, Attr, 1) ||
- !checkAttributeAtMostNumArgs(S, Attr, 2))
- return;
-
- const auto *FD = cast<FunctionDecl>(D);
- if (!FD->getReturnType()->isPointerType()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
- << Attr.getName();
- return;
- }
-
- const Expr *SizeExpr = Attr.getArgAsExpr(0);
- int SizeArgNo;
- // Paramater indices are 1-indexed, hence Index=1
- if (!checkPositiveIntArgument(S, Attr, SizeExpr, SizeArgNo, /*Index=*/1))
- return;
-
- if (!checkParamIsIntegerType(S, FD, Attr, SizeArgNo, /*AttrArgNo=*/0))
- return;
-
- // Args are 1-indexed, so 0 implies that the arg was not present
- int NumberArgNo = 0;
- if (Attr.getNumArgs() == 2) {
- const Expr *NumberExpr = Attr.getArgAsExpr(1);
- // Paramater indices are 1-based, hence Index=2
- if (!checkPositiveIntArgument(S, Attr, NumberExpr, NumberArgNo,
- /*Index=*/2))
- return;
-
- if (!checkParamIsIntegerType(S, FD, Attr, NumberArgNo, /*AttrArgNo=*/1))
- return;
- }
-
- D->addAttr(::new (S.Context) AllocSizeAttr(
- Attr.getRange(), S.Context, SizeArgNo, NumberArgNo,
- Attr.getAttributeSpellingListIndex()));
-}
static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
@@ -5637,9 +5552,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_AlignValue:
handleAlignValueAttr(S, D, Attr);
break;
- case AttributeList::AT_AllocSize:
- handleAllocSizeAttr(S, D, Attr);
- break;
case AttributeList::AT_AlwaysInline:
handleAlwaysInlineAttr(S, D, Attr);
break;
diff --git a/clang/test/CodeGen/alloc-size.c b/clang/test/CodeGen/alloc-size.c
deleted file mode 100644
index 1e503f0579c..00000000000
--- a/clang/test/CodeGen/alloc-size.c
+++ /dev/null
@@ -1,352 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s
-
-#define NULL ((void *)0)
-
-int gi;
-
-typedef unsigned long size_t;
-
-// CHECK-DAG-RE: define void @my_malloc({{.*}}) #[[MALLOC_ATTR_NUMBER:[0-9]+]]
-// N.B. LLVM's allocsize arguments are base-0, whereas ours are base-1 (for
-// compat with GCC)
-// CHECK-DAG-RE: attributes #[[MALLOC_ATTR_NUMBER]] = {.*allocsize(0).*}
-void *my_malloc(size_t) __attribute__((alloc_size(1)));
-
-// CHECK-DAG-RE: define void @my_calloc({{.*}}) #[[CALLOC_ATTR_NUMBER:[0-9]+]]
-// CHECK-DAG-RE: attributes #[[CALLOC_ATTR_NUMBER]] = {.*allocsize(0, 1).*}
-void *my_calloc(size_t, size_t) __attribute__((alloc_size(1, 2)));
-
-// CHECK-LABEL: @test1
-void test1() {
- void *const vp = my_malloc(100);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 0);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 1);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 2);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 3);
-
- void *const arr = my_calloc(100, 5);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 0);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 1);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 2);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 3);
-
- // CHECK: store i32 100
- gi = __builtin_object_size(my_malloc(100), 0);
- // CHECK: store i32 100
- gi = __builtin_object_size(my_malloc(100), 1);
- // CHECK: store i32 100
- gi = __builtin_object_size(my_malloc(100), 2);
- // CHECK: store i32 100
- gi = __builtin_object_size(my_malloc(100), 3);
-
- // CHECK: store i32 500
- gi = __builtin_object_size(my_calloc(100, 5), 0);
- // CHECK: store i32 500
- gi = __builtin_object_size(my_calloc(100, 5), 1);
- // CHECK: store i32 500
- gi = __builtin_object_size(my_calloc(100, 5), 2);
- // CHECK: store i32 500
- gi = __builtin_object_size(my_calloc(100, 5), 3);
-
- void *const zeroPtr = my_malloc(0);
- // CHECK: store i32 0
- gi = __builtin_object_size(zeroPtr, 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(my_malloc(0), 0);
-
- void *const zeroArr1 = my_calloc(0, 1);
- void *const zeroArr2 = my_calloc(1, 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(zeroArr1, 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(zeroArr2, 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(my_calloc(1, 0), 0);
- // CHECK: store i32 0
- gi = __builtin_object_size(my_calloc(0, 1), 0);
-}
-
-// CHECK-LABEL: @test2
-void test2() {
- void *const vp = my_malloc(gi);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(vp, 0);
-
- void *const arr1 = my_calloc(gi, 1);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr1, 0);
-
- void *const arr2 = my_calloc(1, gi);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr2, 0);
-}
-
-// CHECK-LABEL: @test3
-void test3() {
- char *const buf = (char *)my_calloc(100, 5);
- // CHECK: store i32 500
- gi = __builtin_object_size(buf, 0);
- // CHECK: store i32 500
- gi = __builtin_object_size(buf, 1);
- // CHECK: store i32 500
- gi = __builtin_object_size(buf, 2);
- // CHECK: store i32 500
- gi = __builtin_object_size(buf, 3);
-}
-
-struct Data {
- int a;
- int t[10];
- char pad[3];
- char end[1];
-};
-
-// CHECK-LABEL: @test5
-void test5() {
- struct Data *const data = my_malloc(sizeof(*data));
- // CHECK: store i32 48
- gi = __builtin_object_size(data, 0);
- // CHECK: store i32 48
- gi = __builtin_object_size(data, 1);
- // CHECK: store i32 48
- gi = __builtin_object_size(data, 2);
- // CHECK: store i32 48
- gi = __builtin_object_size(data, 3);
-
- // CHECK: store i32 40
- gi = __builtin_object_size(&data->t[1], 0);
- // CHECK: store i32 36
- gi = __builtin_object_size(&data->t[1], 1);
- // CHECK: store i32 40
- gi = __builtin_object_size(&data->t[1], 2);
- // CHECK: store i32 36
- gi = __builtin_object_size(&data->t[1], 3);
-
- struct Data *const arr = my_calloc(sizeof(*data), 2);
- // CHECK: store i32 96
- gi = __builtin_object_size(arr, 0);
- // CHECK: store i32 96
- gi = __builtin_object_size(arr, 1);
- // CHECK: store i32 96
- gi = __builtin_object_size(arr, 2);
- // CHECK: store i32 96
- gi = __builtin_object_size(arr, 3);
-
- // CHECK: store i32 88
- gi = __builtin_object_size(&arr->t[1], 0);
- // CHECK: store i32 36
- gi = __builtin_object_size(&arr->t[1], 1);
- // CHECK: store i32 88
- gi = __builtin_object_size(&arr->t[1], 2);
- // CHECK: store i32 36
- gi = __builtin_object_size(&arr->t[1], 3);
-}
-
-// CHECK-LABEL: @test6
-void test6() {
- // Things that would normally trigger conservative estimates don't need to do
- // so when we know the source of the allocation.
- struct Data *const data = my_malloc(sizeof(*data) + 10);
- // CHECK: store i32 11
- gi = __builtin_object_size(data->end, 0);
- // CHECK: store i32 11
- gi = __builtin_object_size(data->end, 1);
- // CHECK: store i32 11
- gi = __builtin_object_size(data->end, 2);
- // CHECK: store i32 11
- gi = __builtin_object_size(data->end, 3);
-
- struct Data *const arr = my_calloc(sizeof(*arr) + 5, 3);
- // AFAICT, GCC treats malloc and calloc identically. So, we should do the
- // same.
- //
- // Additionally, GCC ignores the initial array index when determining whether
- // we're writing off the end of an alloc_size base. e.g.
- // arr[0].end
- // arr[1].end
- // arr[2].end
- // ...Are all considered "writing off the end", because there's no way to tell
- // with high accuracy if the user meant "allocate a single N-byte `Data`",
- // or "allocate M smaller `Data`s with extra padding".
-
- // CHECK: store i32 112
- gi = __builtin_object_size(arr->end, 0);
- // CHECK: store i32 112
- gi = __builtin_object_size(arr->end, 1);
- // CHECK: store i32 112
- gi = __builtin_object_size(arr->end, 2);
- // CHECK: store i32 112
- gi = __builtin_object_size(arr->end, 3);
-
- // CHECK: store i32 112
- gi = __builtin_object_size(arr[0].end, 0);
- // CHECK: store i32 112
- gi = __builtin_object_size(arr[0].end, 1);
- // CHECK: store i32 112
- gi = __builtin_object_size(arr[0].end, 2);
- // CHECK: store i32 112
- gi = __builtin_object_size(arr[0].end, 3);
-
- // CHECK: store i32 64
- gi = __builtin_object_size(arr[1].end, 0);
- // CHECK: store i32 64
- gi = __builtin_object_size(arr[1].end, 1);
- // CHECK: store i32 64
- gi = __builtin_object_size(arr[1].end, 2);
- // CHECK: store i32 64
- gi = __builtin_object_size(arr[1].end, 3);
-
- // CHECK: store i32 16
- gi = __builtin_object_size(arr[2].end, 0);
- // CHECK: store i32 16
- gi = __builtin_object_size(arr[2].end, 1);
- // CHECK: store i32 16
- gi = __builtin_object_size(arr[2].end, 2);
- // CHECK: store i32 16
- gi = __builtin_object_size(arr[2].end, 3);
-}
-
-// CHECK-LABEL: @test7
-void test7() {
- struct Data *const data = my_malloc(sizeof(*data) + 5);
- // CHECK: store i32 9
- gi = __builtin_object_size(data->pad, 0);
- // CHECK: store i32 3
- gi = __builtin_object_size(data->pad, 1);
- // CHECK: store i32 9
- gi = __builtin_object_size(data->pad, 2);
- // CHECK: store i32 3
- gi = __builtin_object_size(data->pad, 3);
-}
-
-// CHECK-LABEL: @test8
-void test8() {
- // Non-const pointers aren't currently supported.
- void *buf = my_calloc(100, 5);
- // CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
- gi = __builtin_object_size(buf, 0);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(buf, 1);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(buf, 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(buf, 3);
-}
-
-// CHECK-LABEL: @test9
-void test9() {
- // Check to be sure that we unwrap things correctly.
- short *const buf0 = (my_malloc(100));
- short *const buf1 = (short*)(my_malloc(100));
- short *const buf2 = ((short*)(my_malloc(100)));
-
- // CHECK: store i32 100
- gi = __builtin_object_size(buf0, 0);
- // CHECK: store i32 100
- gi = __builtin_object_size(buf1, 0);
- // CHECK: store i32 100
- gi = __builtin_object_size(buf2, 0);
-}
-
-// CHECK-LABEL: @test10
-void test10() {
- // Yay overflow
- short *const arr = my_calloc((size_t)-1 / 2 + 1, 2);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr, 0);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr, 1);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr, 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(arr, 3);
-
- // As an implementation detail, CharUnits can't handle numbers greater than or
- // equal to 2**63. Realistically, this shouldn't be a problem, but we should
- // be sure we don't emit crazy results for this case.
- short *const buf = my_malloc((size_t)-1);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(buf, 0);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(buf, 1);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(buf, 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(buf, 3);
-
- short *const arr_big = my_calloc((size_t)-1 / 2 - 1, 2);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr_big, 0);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr_big, 1);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr_big, 2);
- // CHECK: store i32 0
- gi = __builtin_object_size(arr_big, 3);
-}
-
-void *my_tiny_malloc(char) __attribute__((alloc_size(1)));
-void *my_tiny_calloc(char, char) __attribute__((alloc_size(1, 2)));
-
-// CHECK-LABEL: @test11
-void test11() {
- void *const vp = my_tiny_malloc(100);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 0);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 1);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 2);
- // CHECK: store i32 100
- gi = __builtin_object_size(vp, 3);
-
- // N.B. This causes char overflow, but not size_t overflow, so it should be
- // supported.
- void *const arr = my_tiny_calloc(100, 5);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 0);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 1);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 2);
- // CHECK: store i32 500
- gi = __builtin_object_size(arr, 3);
-}
-
-void *my_signed_malloc(long) __attribute__((alloc_size(1)));
-void *my_signed_calloc(long, long) __attribute__((alloc_size(1, 2)));
-
-// CHECK-LABEL: @test12
-void test12() {
- // CHECK: store i32 100
- gi = __builtin_object_size(my_signed_malloc(100), 0);
- // CHECK: store i32 500
- gi = __builtin_object_size(my_signed_calloc(100, 5), 0);
-
- void *const vp = my_signed_malloc(-2);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(vp, 0);
- // N.B. These get lowered to -1 because the function calls may have
- // side-effects, and we can't determine the objectsize.
- // CHECK: store i32 -1
- gi = __builtin_object_size(my_signed_malloc(-2), 0);
-
- void *const arr1 = my_signed_calloc(-2, 1);
- void *const arr2 = my_signed_calloc(1, -2);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr1, 0);
- // CHECK: @llvm.objectsize
- gi = __builtin_object_size(arr2, 0);
- // CHECK: store i32 -1
- gi = __builtin_object_size(my_signed_calloc(1, -2), 0);
- // CHECK: store i32 -1
- gi = __builtin_object_size(my_signed_calloc(-2, 1), 0);
-}
diff --git a/clang/test/CodeGenCXX/alloc-size.cpp b/clang/test/CodeGenCXX/alloc-size.cpp
deleted file mode 100644
index e93e231b70e..00000000000
--- a/clang/test/CodeGenCXX/alloc-size.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s
-
-namespace templates {
-void *my_malloc(int N) __attribute__((alloc_size(1)));
-void *my_calloc(int N, int M) __attribute__((alloc_size(1, 2)));
-
-struct MyType {
- int arr[4];
-};
-
-template <typename T> int callMalloc();
-
-template <typename T, int N> int callCalloc();
-
-// CHECK-LABEL: define i32 @_ZN9templates6testItEv()
-int testIt() {
- // CHECK: call i32 @_ZN9templates10callMallocINS_6MyTypeEEEiv
- // CHECK: call i32 @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
- return callMalloc<MyType>() + callCalloc<MyType, 4>();
-}
-
-// CHECK-LABEL: define linkonce_odr i32
-// @_ZN9templates10callMallocINS_6MyTypeEEEiv
-template <typename T> int callMalloc() {
- static_assert(sizeof(T) == 16, "");
- // CHECK: ret i32 16
- return __builtin_object_size(my_malloc(sizeof(T)), 0);
-}
-
-// CHECK-LABEL: define linkonce_odr i32
-// @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
-template <typename T, int N> int callCalloc() {
- static_assert(sizeof(T) * N == 64, "");
- // CHECK: ret i32 64
- return __builtin_object_size(my_malloc(sizeof(T) * N), 0);
-}
-}
-
-namespace templated_alloc_size {
-using size_t = unsigned long;
-
-// We don't need bodies for any of these, because they're only used in
-// __builtin_object_size, and that shouldn't need anything but a function
-// decl with alloc_size on it.
-template <typename T>
-T *my_malloc(size_t N = sizeof(T)) __attribute__((alloc_size(1)));
-
-template <typename T>
-T *my_calloc(size_t M, size_t N = sizeof(T)) __attribute__((alloc_size(2, 1)));
-
-template <size_t N>
-void *dependent_malloc(size_t NT = N) __attribute__((alloc_size(1)));
-
-template <size_t N, size_t M>
-void *dependent_calloc(size_t NT = N, size_t MT = M)
- __attribute__((alloc_size(1, 2)));
-
-template <typename T, size_t M>
-void *dependent_calloc2(size_t NT = sizeof(T), size_t MT = M)
- __attribute__((alloc_size(1, 2)));
-
-// CHECK-LABEL: define i32 @_ZN20templated_alloc_size6testItEv
-int testIt() {
- // 122 = 4 + 5*4 + 6 + 7*8 + 4*9
- // CHECK: ret i32 122
- return __builtin_object_size(my_malloc<int>(), 0) +
- __builtin_object_size(my_calloc<int>(5), 0) +
- __builtin_object_size(dependent_malloc<6>(), 0) +
- __builtin_object_size(dependent_calloc<7, 8>(), 0) +
- __builtin_object_size(dependent_calloc2<int, 9>(), 0);
-}
-}
diff --git a/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp b/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp
index 0ec9db1db72..0dc0ab00437 100644
--- a/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp
+++ b/clang/test/CodeGenCXX/block-in-ctor-dtor.cpp
@@ -42,5 +42,7 @@ X::~X() {
// CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke_
// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke
// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke_
+// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke
+// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_
diff --git a/clang/test/CodeGenCXX/global-init.cpp b/clang/test/CodeGenCXX/global-init.cpp
index 1e8694dd42a..e806af9eacb 100644
--- a/clang/test/CodeGenCXX/global-init.cpp
+++ b/clang/test/CodeGenCXX/global-init.cpp
@@ -18,6 +18,9 @@ struct D { ~D(); };
// CHECK: @__dso_handle = external global i8
// CHECK: @c = global %struct.C zeroinitializer, align 8
+// It's okay if we ever implement the IR-generation optimization to remove this.
+// CHECK: @_ZN5test3L3varE = internal constant i8* getelementptr inbounds ([7 x i8], [7 x i8]*
+
// PR6205: The casts should not require global initializers
// CHECK: @_ZN6PR59741cE = external global %"struct.PR5974::C"
// CHECK: @_ZN6PR59741aE = global %"struct.PR5974::A"* getelementptr inbounds (%"struct.PR5974::C", %"struct.PR5974::C"* @_ZN6PR59741cE, i32 0, i32 0)
diff --git a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
index 9986f579957..77ec747f873 100644
--- a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
+++ b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
@@ -3,8 +3,6 @@
typedef void (^bl_t)(local void *);
-// N.B. The check here only exists to set BL_GLOBAL
-// COMMON: @block_G = {{.*}}bitcast ([[BL_GLOBAL:[^@]+@__block_literal_global(\.[0-9]+)?]]
const bl_t block_G = (bl_t) ^ (local void *a) {};
kernel void device_side_enqueue(global int *a, global int *b, int i) {
@@ -124,24 +122,28 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) {
},
4294967296L);
- // The full type of these expressions are long (and repeated elsewhere), so we
- // capture it as part of the regex for convenience and clarity.
- // COMMON: store void ()* bitcast ([[BL_A:[^@]+@__block_literal_global.[0-9]+]] to void ()*), void ()** %block_A
+
void (^const block_A)(void) = ^{
return;
};
-
- // COMMON: store void (i8 addrspace(2)*)* bitcast ([[BL_B:[^@]+@__block_literal_global.[0-9]+]] to void (i8 addrspace(2)*)*), void (i8 addrspace(2)*)** %block_B
void (^const block_B)(local void *) = ^(local void *a) {
return;
};
- // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* bitcast ([[BL_A]] to i8*))
+ // COMMON: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A
+ // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
+ // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* [[BL_I8]])
unsigned size = get_kernel_work_group_size(block_A);
- // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* bitcast ([[BL_B]] to i8*))
+ // COMMON: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)** %block_B
+ // COMMON: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*
+ // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* [[BL_I8]])
size = get_kernel_work_group_size(block_B);
- // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* bitcast ([[BL_A]] to i8*))
+ // COMMON: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A
+ // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
+ // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* [[BL_I8]])
size = get_kernel_preferred_work_group_size_multiple(block_A);
- // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* bitcast ([[BL_GLOBAL]] to i8*))
+ // COMMON: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)* addrspace(1)* @block_G
+ // COMMON: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*
+ // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* [[BL_I8]])
size = get_kernel_preferred_work_group_size_multiple(block_G);
}
diff --git a/clang/test/Sema/alloc-size.c b/clang/test/Sema/alloc-size.c
deleted file mode 100644
index 600ef6870e9..00000000000
--- a/clang/test/Sema/alloc-size.c
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: %clang_cc1 %s -verify
-
-void *fail1(int a) __attribute__((alloc_size)); //expected-error{{'alloc_size' attribute takes at least 1 argument}}
-void *fail2(int a) __attribute__((alloc_size())); //expected-error{{'alloc_size' attribute takes at least 1 argument}}
-
-void *fail3(int a) __attribute__((alloc_size(0))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
-void *fail4(int a) __attribute__((alloc_size(2))); //expected-error{{'alloc_size' attribute parameter 2 is out of bounds}}
-
-void *fail5(int a, int b) __attribute__((alloc_size(0, 1))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
-void *fail6(int a, int b) __attribute__((alloc_size(3, 1))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}
-
-void *fail7(int a, int b) __attribute__((alloc_size(1, 0))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}
-void *fail8(int a, int b) __attribute__((alloc_size(1, 3))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}
-
-int fail9(int a) __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to return values that are pointers}}
-
-int fail10 __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to non-K&R-style functions}}
-
-void *fail11(void *a) __attribute__((alloc_size(1))); //expected-error{{'alloc_size' attribute argument may only refer to a function parameter of integer type}}
-
-void *fail12(int a) __attribute__((alloc_size("abc"))); //expected-error{{'alloc_size' attribute requires parameter 1 to be an integer constant}}
-void *fail12(int a) __attribute__((alloc_size(1, "abc"))); //expected-error{{'alloc_size' attribute requires parameter 2 to be an integer constant}}
-void *fail13(int a) __attribute__((alloc_size(1U<<31))); //expected-error{{integer constant expression evaluates to value 2147483648 that cannot be represented in a 32-bit signed integer type}}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 9ec8318b9e0..0b7528281ac 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1183,7 +1183,7 @@ constexpr int m1b = const_cast<const int&>(n1); // expected-error {{constant exp
constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}}
struct T { int n; };
-const T t = { 42 };
+const T t = { 42 }; // expected-note {{declared here}}
constexpr int f(volatile int &&r) {
return r; // expected-note {{read of volatile-qualified type 'volatile int'}}
@@ -1195,7 +1195,7 @@ struct S {
int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}}
int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}}
int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}}
- int m : t.n; // expected-warning{{width of bit-field 'm' (42 bits)}}
+ int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}}
};
}
OpenPOWER on IntegriCloud