[cfe-commits] r147384 - in /cfe/trunk: lib/AST/ExprConstant.cpp lib/AST/Type.cpp lib/CodeGen/CGDecl.cpp test/CXX/expr/expr.const/p2-0x.cpp test/CXX/special/class.ctor/p6-0x.cpp test/CodeGenCXX/value-init.cpp test/SemaCXX/constexpr-printing.cpp test/SemaCXX/constexpr-value-init.cpp test/SemaObjCXX/arc-type-traits.mm
Richard Smith
richard-llvm at metafoo.co.uk
Fri Dec 30 13:15:52 PST 2011
Author: rsmith
Date: Fri Dec 30 15:15:51 2011
New Revision: 147384
URL: http://llvm.org/viewvc/llvm-project?rev=147384&view=rev
Log:
Unrevert r147271, reverted in r147361.
Also temporarily remove the assumption from IR gen that we can emit IR for every
constant we can fold, since it isn't currently true in C++11, to fix PR11676.
Original comment from r147271:
constexpr: perform zero-initialization prior to / instead of performing a
constructor call when appropriate. Thanks to Eli for spotting this.
Added:
cfe/trunk/test/SemaCXX/constexpr-value-init.cpp
- copied unchanged from r147361, cfe/trunk/test/SemaCXX/constexpr-value-init.cpp
Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
cfe/trunk/test/CXX/special/class.ctor/p6-0x.cpp
cfe/trunk/test/CodeGenCXX/value-init.cpp
cfe/trunk/test/SemaCXX/constexpr-printing.cpp
cfe/trunk/test/SemaObjCXX/arc-type-traits.mm
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Dec 30 15:15:51 2011
@@ -767,9 +767,25 @@
return true;
}
+/// Check that this core constant expression is of literal type, and if not,
+/// produce an appropriate diagnostic.
+static bool CheckLiteralType(EvalInfo &Info, const Expr *E) {
+ if (!E->isRValue() || E->getType()->isLiteralType())
+ return true;
+
+ // Prvalue constant expressions must be of literal types.
+ if (Info.getLangOpts().CPlusPlus0x)
+ Info.Diag(E->getExprLoc(), diag::note_constexpr_nonliteral)
+ << E->getType();
+ else
+ Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+ return false;
+}
+
/// Check that this core constant expression value is a valid value for a
/// constant expression, and if it is, produce the corresponding constant value.
-/// If not, report an appropriate diagnostic.
+/// If not, report an appropriate diagnostic. Does not check that the expression
+/// is of literal type.
static bool CheckConstantExpression(EvalInfo &Info, const Expr *E,
const CCValue &CCValue, APValue &Value,
CheckConstantExpressionKind CCEK
@@ -1644,17 +1660,23 @@
/// constexpr. If it is marked as constexpr, we will never implicitly define it,
/// so we need special handling.
static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc,
- const CXXConstructorDecl *CD) {
+ const CXXConstructorDecl *CD,
+ bool IsValueInitialization) {
if (!CD->isTrivial() || !CD->isDefaultConstructor())
return false;
if (!CD->isConstexpr()) {
if (Info.getLangOpts().CPlusPlus0x) {
- // FIXME: If DiagDecl is an implicitly-declared special member function,
- // we should be much more explicit about why it's not constexpr.
- Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1)
- << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD;
- Info.Note(CD->getLocation(), diag::note_declared_at);
+ // Value-initialization does not call a trivial default constructor, so
+ // such a call is a core constant expression whether or not the
+ // constructor is constexpr.
+ if (!IsValueInitialization) {
+ // FIXME: If DiagDecl is an implicitly-declared special member function,
+ // we should be much more explicit about why it's not constexpr.
+ Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1)
+ << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD;
+ Info.Note(CD->getLocation(), diag::note_declared_at);
+ }
} else {
Info.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
}
@@ -1720,8 +1742,7 @@
static bool HandleConstructorCall(const Expr *CallExpr, const LValue &This,
ArrayRef<const Expr*> Args,
const CXXConstructorDecl *Definition,
- EvalInfo &Info,
- APValue &Result) {
+ EvalInfo &Info, APValue &Result) {
if (!Info.CheckCallLimit(CallExpr->getExprLoc()))
return false;
@@ -1740,7 +1761,7 @@
// Reserve space for the struct members.
const CXXRecordDecl *RD = Definition->getParent();
- if (!RD->isUnion())
+ if (!RD->isUnion() && Result.isUninit())
Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
std::distance(RD->field_begin(), RD->field_end()));
@@ -1909,8 +1930,8 @@
RetTy DerivedSuccess(const CCValue &V, const Expr *E) {
return static_cast<Derived*>(this)->Success(V, E);
}
- RetTy DerivedValueInitialization(const Expr *E) {
- return static_cast<Derived*>(this)->ValueInitialization(E);
+ RetTy DerivedZeroInitialization(const Expr *E) {
+ return static_cast<Derived*>(this)->ZeroInitialization(E);
}
protected:
@@ -1932,7 +1953,7 @@
return Error(E, diag::note_invalid_subexpr_in_const_expr);
}
- RetTy ValueInitialization(const Expr *E) { return Error(E); }
+ RetTy ZeroInitialization(const Expr *E) { return Error(E); }
public:
ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
@@ -2109,20 +2130,20 @@
RetTy VisitInitListExpr(const InitListExpr *E) {
if (Info.getLangOpts().CPlusPlus0x) {
if (E->getNumInits() == 0)
- return DerivedValueInitialization(E);
+ return DerivedZeroInitialization(E);
if (E->getNumInits() == 1)
return StmtVisitorTy::Visit(E->getInit(0));
}
return Error(E);
}
RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
- return DerivedValueInitialization(E);
+ return DerivedZeroInitialization(E);
}
RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
- return DerivedValueInitialization(E);
+ return DerivedZeroInitialization(E);
}
RetTy VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
- return DerivedValueInitialization(E);
+ return DerivedZeroInitialization(E);
}
/// A member expression where the object is a prvalue is itself a prvalue.
@@ -2511,7 +2532,7 @@
Result.setFrom(V);
return true;
}
- bool ValueInitialization(const Expr *E) {
+ bool ZeroInitialization(const Expr *E) {
return Success((Expr*)0);
}
@@ -2631,7 +2652,7 @@
return HandleBaseToDerivedCast(Info, E, Result);
case CK_NullToPointer:
- return ValueInitialization(E);
+ return ZeroInitialization(E);
case CK_IntegralToPointer: {
CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
@@ -2704,7 +2725,7 @@
Result.setFrom(V);
return true;
}
- bool ValueInitialization(const Expr *E) {
+ bool ZeroInitialization(const Expr *E) {
return Success((const ValueDecl*)0);
}
@@ -2725,7 +2746,7 @@
return ExprEvaluatorBaseTy::VisitCastExpr(E);
case CK_NullToMemberPointer:
- return ValueInitialization(E);
+ return ZeroInitialization(E);
case CK_BaseToDerivedMemberPointer: {
if (!Visit(E->getSubExpr()))
@@ -2786,6 +2807,7 @@
bool Success(const CCValue &V, const Expr *E) {
return CheckConstantExpression(Info, E, V, Result);
}
+ bool ZeroInitialization(const Expr *E);
bool VisitCastExpr(const CastExpr *E);
bool VisitInitListExpr(const InitListExpr *E);
@@ -2793,6 +2815,75 @@
};
}
+/// Perform zero-initialization on an object of non-union class type.
+/// C++11 [dcl.init]p5:
+/// To zero-initialize an object or reference of type T means:
+/// [...]
+/// -- if T is a (possibly cv-qualified) non-union class type,
+/// each non-static data member and each base-class subobject is
+/// zero-initialized
+static bool HandleClassZeroInitialization(EvalInfo &Info, const RecordDecl *RD,
+ const LValue &This, APValue &Result) {
+ assert(!RD->isUnion() && "Expected non-union class type");
+ const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD);
+ Result = APValue(APValue::UninitStruct(), CD ? CD->getNumBases() : 0,
+ std::distance(RD->field_begin(), RD->field_end()));
+
+ const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
+
+ if (CD) {
+ unsigned Index = 0;
+ for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(),
+ E = CD->bases_end(); I != E; ++I, ++Index) {
+ const CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
+ LValue Subobject = This;
+ HandleLValueDirectBase(Info, Subobject, CD, Base, &Layout);
+ if (!HandleClassZeroInitialization(Info, Base, Subobject,
+ Result.getStructBase(Index)))
+ return false;
+ }
+ }
+
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I) {
+ // -- if T is a reference type, no initialization is performed.
+ if ((*I)->getType()->isReferenceType())
+ continue;
+
+ LValue Subobject = This;
+ HandleLValueMember(Info, Subobject, *I, &Layout);
+
+ ImplicitValueInitExpr VIE((*I)->getType());
+ if (!EvaluateConstantExpression(
+ Result.getStructField((*I)->getFieldIndex()), Info, Subobject, &VIE))
+ return false;
+ }
+
+ return true;
+}
+
+bool RecordExprEvaluator::ZeroInitialization(const Expr *E) {
+ const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl();
+ if (RD->isUnion()) {
+ // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
+ // object's first non-static named data member is zero-initialized
+ RecordDecl::field_iterator I = RD->field_begin();
+ if (I == RD->field_end()) {
+ Result = APValue((const FieldDecl*)0);
+ return true;
+ }
+
+ LValue Subobject = This;
+ HandleLValueMember(Info, Subobject, *I);
+ Result = APValue(*I);
+ ImplicitValueInitExpr VIE((*I)->getType());
+ return EvaluateConstantExpression(Result.getUnionValue(), Info,
+ Subobject, &VIE);
+ }
+
+ return HandleClassZeroInitialization(Info, RD, This, Result);
+}
+
bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) {
switch (E->getCastKind()) {
default:
@@ -2876,7 +2967,11 @@
bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
const CXXConstructorDecl *FD = E->getConstructor();
- if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD)) {
+ bool ZeroInit = E->requiresZeroInitialization();
+ if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
+ if (ZeroInit)
+ return ZeroInitialization(E);
+
const CXXRecordDecl *RD = FD->getParent();
if (RD->isUnion())
Result = APValue((FieldDecl*)0);
@@ -2893,11 +2988,14 @@
return false;
// FIXME: Elide the copy/move construction wherever we can.
- if (E->isElidable())
+ if (E->isElidable() && !ZeroInit)
if (const MaterializeTemporaryExpr *ME
= dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))
return Visit(ME->GetTemporaryExpr());
+ if (ZeroInit && !ZeroInitialization(E))
+ return false;
+
llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs());
return HandleConstructorCall(E, This, Args,
cast<CXXConstructorDecl>(Definition), Info,
@@ -2907,7 +3005,6 @@
static bool EvaluateRecord(const Expr *E, const LValue &This,
APValue &Result, EvalInfo &Info) {
assert(E->isRValue() && E->getType()->isRecordType() &&
- E->getType()->isLiteralType() &&
"can't evaluate expression as a record rvalue");
return RecordExprEvaluator(Info, This, Result).Visit(E);
}
@@ -2957,14 +3054,6 @@
/// Evaluate an expression of record type as a temporary.
static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) {
assert(E->isRValue() && E->getType()->isRecordType());
- if (!E->getType()->isLiteralType()) {
- if (Info.getLangOpts().CPlusPlus0x)
- Info.Diag(E->getExprLoc(), diag::note_constexpr_nonliteral)
- << E->getType();
- else
- Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
- return false;
- }
return TemporaryExprEvaluator(Info, Result).Visit(E);
}
@@ -2992,7 +3081,7 @@
Result = V;
return true;
}
- bool ValueInitialization(const Expr *E);
+ bool ZeroInitialization(const Expr *E);
bool VisitUnaryReal(const UnaryOperator *E)
{ return Visit(E->getSubExpr()); }
@@ -3144,7 +3233,7 @@
}
bool
-VectorExprEvaluator::ValueInitialization(const Expr *E) {
+VectorExprEvaluator::ZeroInitialization(const Expr *E) {
const VectorType *VT = E->getType()->getAs<VectorType>();
QualType EltTy = VT->getElementType();
APValue ZeroElement;
@@ -3160,7 +3249,7 @@
bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
VisitIgnoredValue(E->getSubExpr());
- return ValueInitialization(E);
+ return ZeroInitialization(E);
}
//===----------------------------------------------------------------------===//
@@ -3183,7 +3272,7 @@
return true;
}
- bool ValueInitialization(const Expr *E) {
+ bool ZeroInitialization(const Expr *E) {
const ConstantArrayType *CAT =
Info.Ctx.getAsConstantArrayType(E->getType());
if (!CAT)
@@ -3193,7 +3282,7 @@
CAT->getSize().getZExtValue());
if (!Result.hasArrayFiller()) return true;
- // Value-initialize all elements.
+ // Zero-initialize all elements.
LValue Subobject = This;
Subobject.Designator.addIndex(0);
ImplicitValueInitExpr VIE(CAT->getElementType());
@@ -3208,8 +3297,7 @@
static bool EvaluateArray(const Expr *E, const LValue &This,
APValue &Result, EvalInfo &Info) {
- assert(E->isRValue() && E->getType()->isArrayType() &&
- E->getType()->isLiteralType() && "not a literal array rvalue");
+ assert(E->isRValue() && E->getType()->isArrayType() && "not an array rvalue");
return ArrayExprEvaluator(Info, This, Result).Visit(E);
}
@@ -3279,7 +3367,16 @@
const CXXConstructorDecl *FD = E->getConstructor();
- if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD)) {
+ bool ZeroInit = E->requiresZeroInitialization();
+ if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
+ if (ZeroInit) {
+ LValue Subobject = This;
+ Subobject.Designator.addIndex(0);
+ ImplicitValueInitExpr VIE(CAT->getElementType());
+ return EvaluateConstantExpression(Result.getArrayFiller(), Info,
+ Subobject, &VIE);
+ }
+
const CXXRecordDecl *RD = FD->getParent();
if (RD->isUnion())
Result.getArrayFiller() = APValue((FieldDecl*)0);
@@ -3302,6 +3399,14 @@
// S s[10];
LValue Subobject = This;
Subobject.Designator.addIndex(0);
+
+ if (ZeroInit) {
+ ImplicitValueInitExpr VIE(CAT->getElementType());
+ if (!EvaluateConstantExpression(Result.getArrayFiller(), Info, Subobject,
+ &VIE))
+ return false;
+ }
+
llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs());
return HandleConstructorCall(E, Subobject, Args,
cast<CXXConstructorDecl>(Definition),
@@ -3365,7 +3470,7 @@
return Success(V.getInt(), E);
}
- bool ValueInitialization(const Expr *E) { return Success(0, E); }
+ bool ZeroInitialization(const Expr *E) { return Success(0, E); }
//===--------------------------------------------------------------------===//
// Visitor Methods
@@ -3408,7 +3513,7 @@
// Note, GNU defines __null as an integer, not a pointer.
bool VisitGNUNullExpr(const GNUNullExpr *E) {
- return ValueInitialization(E);
+ return ZeroInitialization(E);
}
bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
@@ -4411,7 +4516,7 @@
return true;
}
- bool ValueInitialization(const Expr *E) {
+ bool ZeroInitialization(const Expr *E) {
Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
return true;
}
@@ -4426,8 +4531,7 @@
bool VisitUnaryReal(const UnaryOperator *E);
bool VisitUnaryImag(const UnaryOperator *E);
- // FIXME: Missing: array subscript of vector, member of vector,
- // ImplicitValueInitExpr
+ // FIXME: Missing: array subscript of vector, member of vector
};
} // end anonymous namespace
@@ -5034,13 +5138,13 @@
return false;
P.moveInto(Result);
return true;
- } else if (E->getType()->isArrayType() && E->getType()->isLiteralType()) {
+ } else if (E->getType()->isArrayType()) {
LValue LV;
LV.set(E, Info.CurrentCall);
if (!EvaluateArray(E, LV, Info.CurrentCall->Temporaries[E], Info))
return false;
Result = Info.CurrentCall->Temporaries[E];
- } else if (E->getType()->isRecordType() && E->getType()->isLiteralType()) {
+ } else if (E->getType()->isRecordType()) {
LValue LV;
LV.set(E, Info.CurrentCall);
if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info))
@@ -5072,7 +5176,10 @@
static bool EvaluateConstantExpression(APValue &Result, EvalInfo &Info,
const LValue &This, const Expr *E,
CheckConstantExpressionKind CCEK) {
- if (E->isRValue() && E->getType()->isLiteralType()) {
+ if (!CheckLiteralType(Info, E))
+ return false;
+
+ if (E->isRValue()) {
// Evaluate arrays and record types in-place, so that later initializers can
// refer to earlier-initialized members of the object.
if (E->getType()->isArrayType())
@@ -5090,6 +5197,9 @@
/// EvaluateAsRValue - Try to evaluate this expression, performing an implicit
/// lvalue-to-rvalue cast if it is an lvalue.
static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
+ if (!CheckLiteralType(Info, E))
+ return false;
+
CCValue Value;
if (!::Evaluate(Value, Info, E))
return false;
@@ -5173,9 +5283,23 @@
EvalInfo InitInfo(Ctx, EStatus);
InitInfo.setEvaluatingDecl(VD, Value);
+ if (!CheckLiteralType(InitInfo, this))
+ return false;
+
LValue LVal;
LVal.set(VD);
+ // C++11 [basic.start.init]p2:
+ // Variables with static storage duration or thread storage duration shall be
+ // zero-initialized before any other initialization takes place.
+ // This behavior is not present in C.
+ if (Ctx.getLangOptions().CPlusPlus && !VD->hasLocalStorage() &&
+ !VD->getType()->isReferenceType()) {
+ ImplicitValueInitExpr VIE(VD->getType());
+ if (!EvaluateConstantExpression(Value, InitInfo, LVal, &VIE))
+ return false;
+ }
+
return EvaluateConstantExpression(Value, InitInfo, LVal, this) &&
!EStatus.HasSideEffects;
}
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Dec 30 15:15:51 2011
@@ -1126,10 +1126,6 @@
if (BaseTy->isIncompleteType())
return false;
- // Objective-C lifetime types are not literal types.
- if (BaseTy->isObjCRetainableType())
- return false;
-
// C++0x [basic.types]p10:
// A type is a literal type if it is:
// -- a scalar type; or
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Dec 30 15:15:51 2011
@@ -970,7 +970,13 @@
llvm::Value *Loc =
capturedByInit ? emission.Address : emission.getObjectAddress(*this);
- if (!emission.IsConstantAggregate) {
+ llvm::Constant *constant = 0;
+ if (emission.IsConstantAggregate) {
+ assert(!capturedByInit && "constant init contains a capturing block?");
+ constant = CGM.EmitConstantExpr(D.getInit(), type, this);
+ }
+
+ if (!constant) {
LValue lv = MakeAddrLValue(Loc, type, alignment);
lv.setNonGC(true);
return EmitExprAsInit(Init, &D, lv, capturedByInit);
@@ -978,13 +984,8 @@
// If this is a simple aggregate initialization, we can optimize it
// in various ways.
- assert(!capturedByInit && "constant init contains a capturing block?");
-
bool isVolatile = type.isVolatileQualified();
- llvm::Constant *constant = CGM.EmitConstantExpr(D.getInit(), type, this);
- assert(constant != 0 && "Wasn't a simple constant init?");
-
llvm::Value *SizeVal =
llvm::ConstantInt::get(IntPtrTy,
getContext().getTypeSizeInChars(type).getQuantity());
Modified: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Fri Dec 30 15:15:51 2011
@@ -33,11 +33,11 @@
int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}}
};
struct NonConstexpr4 {
- NonConstexpr4();
+ NonConstexpr4(); // expected-note {{declared here}}
int n;
};
struct NonConstexpr5 {
- int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-literal type 'NonConstexpr4' cannot be used in a constant expression}}
+ int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4' cannot be used in a constant expression}}
};
// - an invocation of an undefined constexpr function or an undefined
Modified: cfe/trunk/test/CXX/special/class.ctor/p6-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p6-0x.cpp?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.ctor/p6-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.ctor/p6-0x.cpp Fri Dec 30 15:15:51 2011
@@ -8,8 +8,16 @@
struct NonConstexpr2 { // expected-note {{here}}
NonConstexpr1 nl;
};
-constexpr NonConstexpr1 nc1 = NonConstexpr1(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr1'}}
-constexpr NonConstexpr2 nc2 = NonConstexpr2(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr2'}}
+struct NonConstexpr2a : NonConstexpr1 { };
+constexpr NonConstexpr1 nc1 = NonConstexpr1(); // ok, does not call constructor
+constexpr NonConstexpr2 nc2 = NonConstexpr2(); // ok, does not call constructor
+constexpr NonConstexpr2a nc2a = NonConstexpr2a(); // expected-error {{constant expression}} expected-note {{non-literal type 'const NonConstexpr2a'}}
+constexpr int nc2_a = NonConstexpr2().nl.a; // ok
+constexpr int nc2a_a = NonConstexpr2a().a; // ok
+struct Helper {
+ friend constexpr NonConstexpr1::NonConstexpr1(); // expected-error {{follows non-constexpr declaration}}
+ friend constexpr NonConstexpr2::NonConstexpr2(); // expected-error {{follows non-constexpr declaration}}
+};
struct Constexpr1 {};
constexpr Constexpr1 c1 = Constexpr1(); // ok
Modified: cfe/trunk/test/CodeGenCXX/value-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/value-init.cpp?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/value-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/value-init.cpp Fri Dec 30 15:15:51 2011
@@ -134,8 +134,7 @@
// CHECK: define i32 @_ZN8zeroinit4testEv()
int test() {
// CHECK: call void @llvm.memset.p0i8.i64
- // CHECK: getelementptr
- // CHECK: ret i32
+ // CHECK: ret i32 0
return S().i;
}
Modified: cfe/trunk/test/SemaCXX/constexpr-printing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-printing.cpp?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constexpr-printing.cpp (original)
+++ cfe/trunk/test/SemaCXX/constexpr-printing.cpp Fri Dec 30 15:15:51 2011
@@ -11,8 +11,11 @@
constexpr int extract(const S &s) { return s.n; } // expected-note {{read of uninitialized object is not allowed in a constant expression}}
-constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}}
-constexpr S s2(10);
+constexpr S s1; // ok
+void f() {
+ constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}}
+ constexpr S s2(10);
+}
typedef __attribute__((vector_size(16))) int vector_int;
Modified: cfe/trunk/test/SemaObjCXX/arc-type-traits.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-type-traits.mm?rev=147384&r1=147383&r2=147384&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-type-traits.mm (original)
+++ cfe/trunk/test/SemaObjCXX/arc-type-traits.mm Fri Dec 30 15:15:51 2011
@@ -53,16 +53,16 @@
TRAIT_IS_TRUE(__has_trivial_destructor, __unsafe_unretained id);
// __is_literal
-TRAIT_IS_FALSE(__is_literal, __strong id);
-TRAIT_IS_FALSE(__is_literal, __weak id);
-TRAIT_IS_FALSE(__is_literal, __autoreleasing id);
-TRAIT_IS_FALSE(__is_literal, __unsafe_unretained id);
+TRAIT_IS_TRUE(__is_literal, __strong id);
+TRAIT_IS_TRUE(__is_literal, __weak id);
+TRAIT_IS_TRUE(__is_literal, __autoreleasing id);
+TRAIT_IS_TRUE(__is_literal, __unsafe_unretained id);
// __is_literal_type
-TRAIT_IS_FALSE(__is_literal_type, __strong id);
-TRAIT_IS_FALSE(__is_literal_type, __weak id);
-TRAIT_IS_FALSE(__is_literal_type, __autoreleasing id);
-TRAIT_IS_FALSE(__is_literal_type, __unsafe_unretained id);
+TRAIT_IS_TRUE(__is_literal_type, __strong id);
+TRAIT_IS_TRUE(__is_literal_type, __weak id);
+TRAIT_IS_TRUE(__is_literal_type, __autoreleasing id);
+TRAIT_IS_TRUE(__is_literal_type, __unsafe_unretained id);
// __is_pod
TRAIT_IS_FALSE(__is_pod, __strong id);
More information about the cfe-commits
mailing list