summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-12-15 02:28:18 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-12-15 02:28:18 +0000
commit81f5ade22790685efa5542bd8b7e7fb2c6b6c56c (patch)
tree23c92251419f2a497e8abcd378c2fa5b8b7849b6 /clang/lib
parent1a328f508f99473907bbca0e5a40e9f57209a5da (diff)
downloadbcm5719-llvm-81f5ade22790685efa5542bd8b7e7fb2c6b6c56c.tar.gz
bcm5719-llvm-81f5ade22790685efa5542bd8b7e7fb2c6b6c56c.zip
Move checks for creation of objects of abstract class type from the various
constructs that can do so into the initialization code. This fixes a number of different cases in which we used to fail to check for abstract types. Thanks to Tim Shen for inspiring the weird code that uncovered this! llvm-svn: 289753
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp7
-rw-r--r--clang/lib/Sema/SemaInit.cpp30
-rw-r--r--clang/lib/Sema/SemaObjCProperty.cpp6
3 files changed, 33 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index a4546cec5ab..74beeac7244 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1291,10 +1291,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
diag::err_invalid_incomplete_type_use, FullRange))
return ExprError();
- if (RequireNonAbstractType(TyBeginLoc, Ty,
- diag::err_allocation_of_abstract_type))
- return ExprError();
-
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
InitializationKind Kind =
Exprs.size() ? ListInitialization
@@ -5491,9 +5487,6 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) {
if (LTy->isRecordType()) {
// The operands have class type. Make a temporary copy.
- if (RequireNonAbstractType(QuestionLoc, LTy,
- diag::err_allocation_of_abstract_type))
- return QualType();
InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
ExprResult LHSCopy = PerformCopyInitialization(Entity,
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 6ece7c8d784..ce012896f5b 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4599,7 +4599,7 @@ static void TryValueInitialization(Sema &S,
MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0);
bool InitListSyntax = InitList;
- // FIXME: Instead of creating a CXXConstructExpr of non-array type here,
+ // FIXME: Instead of creating a CXXConstructExpr of array type here,
// wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr.
return TryConstructorInitialization(
S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax);
@@ -6366,6 +6366,8 @@ ExprResult Sema::TemporaryMaterializationConversion(Expr *E) {
return E;
// C++1z [conv.rval]/1: T shall be a complete type.
+ // FIXME: Does this ever matter (can we form a prvalue of incomplete type)?
+ // If so, we should check for a non-abstract class type here too.
QualType T = E->getType();
if (RequireCompleteType(E->getExprLoc(), T, diag::err_incomplete_type))
return ExprError();
@@ -6541,6 +6543,17 @@ InitializationSequence::Perform(Sema &S,
break;
}
+ // C++ [class.abstract]p2:
+ // no objects of an abstract class can be created except as subobjects
+ // of a class derived from it
+ auto checkAbstractType = [&](QualType T) -> bool {
+ if (Entity.getKind() == InitializedEntity::EK_Base ||
+ Entity.getKind() == InitializedEntity::EK_Delegating)
+ return false;
+ return S.RequireNonAbstractType(Kind.getLocation(), T,
+ diag::err_allocation_of_abstract_type);
+ };
+
// Walk through the computed steps for the initialization sequence,
// performing the specified conversions along the way.
bool ConstructorInitRequiresZeroInit = false;
@@ -6647,6 +6660,9 @@ InitializationSequence::Perform(Sema &S,
}
case SK_FinalCopy:
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
// If the overall initialization is initializing a temporary, we already
// bound our argument if it was necessary to do so. If not (if we're
// ultimately initializing a non-temporary), our argument needs to be
@@ -6731,6 +6747,9 @@ InitializationSequence::Perform(Sema &S,
CreatedObject = Conversion->getReturnType()->isRecordType();
}
+ if (CreatedObject && checkAbstractType(CurInit.get()->getType()))
+ return ExprError();
+
CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(),
CastKind, CurInit.get(), nullptr,
CurInit.get()->getValueKind());
@@ -6813,6 +6832,9 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ListInitialization: {
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
// If we're not initializing the top-level entity, we need to create an
// InitializeTemporary entity for our target type.
@@ -6849,6 +6871,9 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ConstructorInitializationFromList: {
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
// When an initializer list is passed for a parameter of type "reference
// to object", we don't get an EK_Temporary entity, but instead an
// EK_Parameter entity with reference type.
@@ -6892,6 +6917,9 @@ InitializationSequence::Perform(Sema &S,
case SK_ConstructorInitialization:
case SK_StdInitializerListConstructorCall: {
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
// When an initializer list is passed for a parameter of type "reference
// to object", we don't get an EK_Temporary entity, but instead an
// EK_Parameter entity with reference type.
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index 9ab80b4f79d..3481b82679c 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1146,9 +1146,11 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
diag::err_abstract_type_in_decl,
AbstractSynthesizedIvarType)) {
Diag(property->getLocation(), diag::note_property_declare);
+ // An abstract type is as bad as an incomplete type.
+ CompleteTypeErr = true;
+ }
+ if (CompleteTypeErr)
Ivar->setInvalidDecl();
- } else if (CompleteTypeErr)
- Ivar->setInvalidDecl();
ClassImpDecl->addDecl(Ivar);
IDecl->makeDeclVisibleInContext(Ivar);
OpenPOWER on IntegriCloud