summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp44
-rw-r--r--clang/lib/Sema/SemaType.cpp55
2 files changed, 93 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b89e2bcc800..9f964fab9cd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/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
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index a2433cad51a..9fccdb11c58 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3246,6 +3246,61 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
} while ((attrs = next));
}
+/// \brief Ensure that the type of the given expression is complete.
+///
+/// This routine checks whether the expression \p E has a complete type. If the
+/// expression refers to an instantiable construct, that instantiation is
+/// performed as needed to complete its type. Furthermore
+/// Sema::RequireCompleteType is called for the expression's type (or in the
+/// case of a reference type, the referred-to type).
+///
+/// \param E The expression whose type is required to be complete.
+/// \param PD The partial diagnostic that will be printed out if the type cannot
+/// be completed.
+///
+/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
+/// otherwise.
+bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
+ std::pair<SourceLocation,
+ PartialDiagnostic> Note) {
+ QualType T = E->getType();
+
+ // Fast path the case where the type is already complete.
+ if (!T->isIncompleteType())
+ return false;
+
+ // Incomplete array types may be completed by the initializer attached to
+ // their definitions. For static data members of class templates we need to
+ // instantiate the definition to get this initializer and complete the type.
+ if (T->isIncompleteArrayType()) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (Var->isStaticDataMember() &&
+ Var->getInstantiatedFromStaticDataMember()) {
+ InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
+ // Update the type to the newly instantiated definition's type both
+ // here and within the expression.
+ T = Var->getDefinition()->getType();
+ E->setType(T);
+
+ // We still go on to try to complete the type independently, as it
+ // may also require instantiations or diagnostics if it remains
+ // incomplete.
+ }
+ }
+ }
+ }
+
+ // FIXME: Are there other cases which require instantiating something other
+ // than the type to complete the type of an expression?
+
+ // Look through reference types and complete the referred type.
+ if (const ReferenceType *Ref = T->getAs<ReferenceType>())
+ T = Ref->getPointeeType();
+
+ return RequireCompleteType(E->getExprLoc(), T, PD, Note);
+}
+
/// @brief Ensure that the type T is a complete type.
///
/// This routine checks whether the type @p T is complete in any
OpenPOWER on IntegriCloud