Revert r147271. This fixes PR11676.

llvm-svn: 147362
This commit is contained in:
Rafael Espindola 2011-12-30 03:11:50 +00:00
parent 6c08930c5e
commit fafe4b7572
8 changed files with 68 additions and 229 deletions

View File

@ -767,25 +767,9 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, const Expr *E,
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. Does not check that the expression
/// is of literal type.
/// If not, report an appropriate diagnostic.
static bool CheckConstantExpression(EvalInfo &Info, const Expr *E,
const CCValue &CCValue, APValue &Value,
CheckConstantExpressionKind CCEK
@ -1660,23 +1644,17 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
/// constexpr. If it is marked as constexpr, we will never implicitly define it,
/// so we need special handling.
static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc,
const CXXConstructorDecl *CD,
bool IsValueInitialization) {
const CXXConstructorDecl *CD) {
if (!CD->isTrivial() || !CD->isDefaultConstructor())
return false;
if (!CD->isConstexpr()) {
if (Info.getLangOpts().CPlusPlus0x) {
// 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);
}
// 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);
}
@ -1742,7 +1720,8 @@ static bool HandleFunctionCall(const Expr *CallExpr, const FunctionDecl *Callee,
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;
@ -1761,7 +1740,7 @@ static bool HandleConstructorCall(const Expr *CallExpr, const LValue &This,
// Reserve space for the struct members.
const CXXRecordDecl *RD = Definition->getParent();
if (!RD->isUnion() && Result.isUninit())
if (!RD->isUnion())
Result = APValue(APValue::UninitStruct(), RD->getNumBases(),
std::distance(RD->field_begin(), RD->field_end()));
@ -1930,8 +1909,8 @@ private:
RetTy DerivedSuccess(const CCValue &V, const Expr *E) {
return static_cast<Derived*>(this)->Success(V, E);
}
RetTy DerivedZeroInitialization(const Expr *E) {
return static_cast<Derived*>(this)->ZeroInitialization(E);
RetTy DerivedValueInitialization(const Expr *E) {
return static_cast<Derived*>(this)->ValueInitialization(E);
}
protected:
@ -1953,7 +1932,7 @@ protected:
return Error(E, diag::note_invalid_subexpr_in_const_expr);
}
RetTy ZeroInitialization(const Expr *E) { return Error(E); }
RetTy ValueInitialization(const Expr *E) { return Error(E); }
public:
ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
@ -2130,20 +2109,20 @@ public:
RetTy VisitInitListExpr(const InitListExpr *E) {
if (Info.getLangOpts().CPlusPlus0x) {
if (E->getNumInits() == 0)
return DerivedZeroInitialization(E);
return DerivedValueInitialization(E);
if (E->getNumInits() == 1)
return StmtVisitorTy::Visit(E->getInit(0));
}
return Error(E);
}
RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
return DerivedZeroInitialization(E);
return DerivedValueInitialization(E);
}
RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
return DerivedZeroInitialization(E);
return DerivedValueInitialization(E);
}
RetTy VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
return DerivedZeroInitialization(E);
return DerivedValueInitialization(E);
}
/// A member expression where the object is a prvalue is itself a prvalue.
@ -2532,7 +2511,7 @@ public:
Result.setFrom(V);
return true;
}
bool ZeroInitialization(const Expr *E) {
bool ValueInitialization(const Expr *E) {
return Success((Expr*)0);
}
@ -2652,7 +2631,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
return HandleBaseToDerivedCast(Info, E, Result);
case CK_NullToPointer:
return ZeroInitialization(E);
return ValueInitialization(E);
case CK_IntegralToPointer: {
CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
@ -2725,7 +2704,7 @@ public:
Result.setFrom(V);
return true;
}
bool ZeroInitialization(const Expr *E) {
bool ValueInitialization(const Expr *E) {
return Success((const ValueDecl*)0);
}
@ -2746,7 +2725,7 @@ bool MemberPointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
return ExprEvaluatorBaseTy::VisitCastExpr(E);
case CK_NullToMemberPointer:
return ZeroInitialization(E);
return ValueInitialization(E);
case CK_BaseToDerivedMemberPointer: {
if (!Visit(E->getSubExpr()))
@ -2807,7 +2786,6 @@ namespace {
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);
@ -2815,75 +2793,6 @@ namespace {
};
}
/// 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:
@ -2967,11 +2876,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
const CXXConstructorDecl *FD = E->getConstructor();
bool ZeroInit = E->requiresZeroInitialization();
if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
if (ZeroInit)
return ZeroInitialization(E);
if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD)) {
const CXXRecordDecl *RD = FD->getParent();
if (RD->isUnion())
Result = APValue((FieldDecl*)0);
@ -2988,14 +2893,11 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return false;
// FIXME: Elide the copy/move construction wherever we can.
if (E->isElidable() && !ZeroInit)
if (E->isElidable())
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,
@ -3005,6 +2907,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
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);
}
@ -3054,6 +2957,14 @@ public:
/// 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);
}
@ -3081,7 +2992,7 @@ namespace {
Result = V;
return true;
}
bool ZeroInitialization(const Expr *E);
bool ValueInitialization(const Expr *E);
bool VisitUnaryReal(const UnaryOperator *E)
{ return Visit(E->getSubExpr()); }
@ -3233,7 +3144,7 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
}
bool
VectorExprEvaluator::ZeroInitialization(const Expr *E) {
VectorExprEvaluator::ValueInitialization(const Expr *E) {
const VectorType *VT = E->getType()->getAs<VectorType>();
QualType EltTy = VT->getElementType();
APValue ZeroElement;
@ -3249,7 +3160,7 @@ VectorExprEvaluator::ZeroInitialization(const Expr *E) {
bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
VisitIgnoredValue(E->getSubExpr());
return ZeroInitialization(E);
return ValueInitialization(E);
}
//===----------------------------------------------------------------------===//
@ -3272,7 +3183,7 @@ namespace {
return true;
}
bool ZeroInitialization(const Expr *E) {
bool ValueInitialization(const Expr *E) {
const ConstantArrayType *CAT =
Info.Ctx.getAsConstantArrayType(E->getType());
if (!CAT)
@ -3282,7 +3193,7 @@ namespace {
CAT->getSize().getZExtValue());
if (!Result.hasArrayFiller()) return true;
// Zero-initialize all elements.
// Value-initialize all elements.
LValue Subobject = This;
Subobject.Designator.addIndex(0);
ImplicitValueInitExpr VIE(CAT->getElementType());
@ -3297,7 +3208,8 @@ namespace {
static bool EvaluateArray(const Expr *E, const LValue &This,
APValue &Result, EvalInfo &Info) {
assert(E->isRValue() && E->getType()->isArrayType() && "not an array rvalue");
assert(E->isRValue() && E->getType()->isArrayType() &&
E->getType()->isLiteralType() && "not a literal array rvalue");
return ArrayExprEvaluator(Info, This, Result).Visit(E);
}
@ -3367,16 +3279,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
const CXXConstructorDecl *FD = E->getConstructor();
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);
}
if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD)) {
const CXXRecordDecl *RD = FD->getParent();
if (RD->isUnion())
Result.getArrayFiller() = APValue((FieldDecl*)0);
@ -3399,14 +3302,6 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
// 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),
@ -3470,7 +3365,7 @@ public:
return Success(V.getInt(), E);
}
bool ZeroInitialization(const Expr *E) { return Success(0, E); }
bool ValueInitialization(const Expr *E) { return Success(0, E); }
//===--------------------------------------------------------------------===//
// Visitor Methods
@ -3513,7 +3408,7 @@ public:
// Note, GNU defines __null as an integer, not a pointer.
bool VisitGNUNullExpr(const GNUNullExpr *E) {
return ZeroInitialization(E);
return ValueInitialization(E);
}
bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
@ -4516,7 +4411,7 @@ public:
return true;
}
bool ZeroInitialization(const Expr *E) {
bool ValueInitialization(const Expr *E) {
Result = APFloat::getZero(Info.Ctx.getFloatTypeSemantics(E->getType()));
return true;
}
@ -4531,7 +4426,8 @@ public:
bool VisitUnaryReal(const UnaryOperator *E);
bool VisitUnaryImag(const UnaryOperator *E);
// FIXME: Missing: array subscript of vector, member of vector
// FIXME: Missing: array subscript of vector, member of vector,
// ImplicitValueInitExpr
};
} // end anonymous namespace
@ -5138,13 +5034,13 @@ static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E) {
return false;
P.moveInto(Result);
return true;
} else if (E->getType()->isArrayType()) {
} else if (E->getType()->isArrayType() && E->getType()->isLiteralType()) {
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()) {
} else if (E->getType()->isRecordType() && E->getType()->isLiteralType()) {
LValue LV;
LV.set(E, Info.CurrentCall);
if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info))
@ -5176,10 +5072,7 @@ static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E) {
static bool EvaluateConstantExpression(APValue &Result, EvalInfo &Info,
const LValue &This, const Expr *E,
CheckConstantExpressionKind CCEK) {
if (!CheckLiteralType(Info, E))
return false;
if (E->isRValue()) {
if (E->isRValue() && E->getType()->isLiteralType()) {
// Evaluate arrays and record types in-place, so that later initializers can
// refer to earlier-initialized members of the object.
if (E->getType()->isArrayType())
@ -5197,9 +5090,6 @@ static bool EvaluateConstantExpression(APValue &Result, EvalInfo &Info,
/// 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;
@ -5283,23 +5173,9 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
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;
}

View File

@ -1126,6 +1126,10 @@ bool Type::isLiteralType() const {
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

View File

@ -33,11 +33,11 @@ struct NonConstexpr3 {
int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}}
};
struct NonConstexpr4 {
NonConstexpr4(); // expected-note {{declared here}}
NonConstexpr4();
int n;
};
struct NonConstexpr5 {
int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4' cannot be used in a constant expression}}
int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-literal type 'NonConstexpr4' cannot be used in a constant expression}}
};
// - an invocation of an undefined constexpr function or an undefined

View File

@ -8,16 +8,8 @@ struct NonConstexpr1 { // expected-note {{here}}
struct NonConstexpr2 { // expected-note {{here}}
NonConstexpr1 nl;
};
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}}
};
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 Constexpr1 {};
constexpr Constexpr1 c1 = Constexpr1(); // ok

View File

@ -134,7 +134,8 @@ namespace zeroinit {
// CHECK: define i32 @_ZN8zeroinit4testEv()
int test() {
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK: ret i32 0
// CHECK: getelementptr
// CHECK: ret i32
return S().i;
}

View File

@ -11,11 +11,8 @@ struct S {
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; // ok
void f() {
constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}}
constexpr S s2(10);
}
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;

View File

@ -1,31 +0,0 @@
// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify
struct A {
constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{uninitialized}}
int a;
int b;
};
struct B {
A a;
};
constexpr A a; // ok, zero initialization preceeds static initialization
void f() {
constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}}
}
constexpr B b1; // expected-error {{requires a user-provided default constructor}}
constexpr B b2 = B(); // ok
static_assert(b2.a.a == 1, "");
static_assert(b2.a.b == 2, "");
struct C {
int c;
};
struct D : C { int d; };
constexpr C c1; // expected-error {{requires a user-provided default constructor}}
constexpr C c2 = C(); // ok
constexpr D d1; // expected-error {{requires a user-provided default constructor}}
constexpr D d2 = D(); // expected-error {{constant expression}} expected-note {{non-literal type 'const D'}}
static_assert(D().c == 0, "");
static_assert(D().d == 0, "");

View File

@ -53,16 +53,16 @@ TRAIT_IS_TRUE(__has_trivial_destructor, __autoreleasing id);
TRAIT_IS_TRUE(__has_trivial_destructor, __unsafe_unretained id);
// __is_literal
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);
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);
// __is_literal_type
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);
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);
// __is_pod
TRAIT_IS_FALSE(__is_pod, __strong id);