diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2011-05-27 01:33:31 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2011-05-27 01:33:31 +0000 |
commit | e4d645cbe073042d8abc1a4eb600af4ff7a8dffb (patch) | |
tree | 20170938ca6135c58b83a163856889f071534bb6 /lib/Sema/SemaExpr.cpp | |
parent | f968d8374791c37bc464efd9168c2d33dd73605f (diff) |
Enhance Clang to start instantiating static data member definitions
within class templates when they are necessary to complete the type of
the member. The canonical example is code like:
template <typename T> struct S {
static const int arr[];
static const int x;
static int f();
};
template <typename T> const int S<T>::arr[] = { 1, 2, 3 };
template <typename T> const int S<T>::x = sizeof(arr) / sizeof(arr[0]);
template <typename T> int S<T>::f() { return x; }
int x = S<int>::f();
We need to instantiate S<T>::arr's definition to pick up its initializer
and complete the array type. This involves new code to specially handle
completing the type of an expression where the type alone is
insufficient. It also requires *updating* the expression with the newly
completed type. Fortunately, all the other infrastructure is already in
Clang to do the instantiation, do the completion, and prune out the
unused bits of code that result from this instantiation.
This addresses the initial bug in PR10001, and will be a step to
fleshing out other cases where we need to work harder to complete an
expression's type. Who knew we still had missing C++03 "features"?
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132172 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b89e2bcc80..9f964fab9c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3111,14 +3111,46 @@ static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T, /// \brief Check the constrains on expression operands to unary type expression /// and type traits. /// -/// This is just a convenience wrapper around -/// Sema::CheckUnaryExprOrTypeTraitOperand. +/// Completes any types necessary and validates the constraints on the operand +/// expression. The logic mostly mirrors the type-based overload, but may modify +/// the expression as it completes the type for that expression through template +/// instantiation, etc. bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *Op, UnaryExprOrTypeTrait ExprKind) { - return CheckUnaryExprOrTypeTraitOperand(Op->getType(), - Op->getExprLoc(), - Op->getSourceRange(), - ExprKind); + QualType ExprTy = Op->getType(); + + // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, + // the result is the size of the referenced type." + // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the + // result shall be the alignment of the referenced type." + if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>()) + ExprTy = Ref->getPointeeType(); + + if (ExprKind == UETT_VecStep) + return CheckVecStepTraitOperandType(*this, ExprTy, Op->getExprLoc(), + Op->getSourceRange()); + + // Whitelist some types as extensions + if (!CheckExtensionTraitOperandType(*this, ExprTy, Op->getExprLoc(), + Op->getSourceRange(), ExprKind)) + return false; + + if (RequireCompleteExprType(Op, + PDiag(diag::err_sizeof_alignof_incomplete_type) + << ExprKind << Op->getSourceRange(), + std::make_pair(SourceLocation(), PDiag(0)))) + return true; + + // Completeing the expression's type may have changed it. + ExprTy = Op->getType(); + if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>()) + ExprTy = Ref->getPointeeType(); + + if (CheckObjCTraitOperandConstraints(*this, ExprTy, Op->getExprLoc(), + Op->getSourceRange(), ExprKind)) + return true; + + return false; } /// \brief Check the constraints on operands to unary expression and type |