diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2016-01-21 12:54:48 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2016-01-21 12:54:48 +0000 |
commit | 93a546a326d679d53ae7314e73bf72b43209d683 (patch) | |
tree | a18be0ed40978f1e16216e4c232eb22cfa6f0a1b /clang/lib/Sema/SemaExpr.cpp | |
parent | 14f9535eecf83a36e275a5f22c51d12febf43c02 (diff) | |
download | bcm5719-llvm-93a546a326d679d53ae7314e73bf72b43209d683.tar.gz bcm5719-llvm-93a546a326d679d53ae7314e73bf72b43209d683.zip |
Fix crash for typedefs for arrays of runtime bounds in Lambdas/Captured Statements, used in sizeof() expression only.
llvm-svn: 258396
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 251 |
1 files changed, 137 insertions, 114 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index aacbda402f7..fc1a9268b16 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3748,6 +3748,128 @@ bool Sema::CheckVecStepExpr(Expr *E) { return CheckUnaryExprOrTypeTraitOperand(E, UETT_VecStep); } +static void captureVariablyModifiedType(ASTContext &Context, QualType T, + CapturingScopeInfo *CSI) { + assert(T->isVariablyModifiedType()); + assert(CSI != nullptr); + + // We're going to walk down into the type and look for VLA expressions. + do { + const Type *Ty = T.getTypePtr(); + switch (Ty->getTypeClass()) { +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_TYPE(Class, Base) +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + T = QualType(); + break; + // These types are never variably-modified. + case Type::Builtin: + case Type::Complex: + case Type::Vector: + case Type::ExtVector: + case Type::Record: + case Type::Enum: + case Type::Elaborated: + case Type::TemplateSpecialization: + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + case Type::Pipe: + llvm_unreachable("type class is never variably-modified!"); + case Type::Adjusted: + T = cast<AdjustedType>(Ty)->getOriginalType(); + break; + case Type::Decayed: + T = cast<DecayedType>(Ty)->getPointeeType(); + break; + case Type::Pointer: + T = cast<PointerType>(Ty)->getPointeeType(); + break; + case Type::BlockPointer: + T = cast<BlockPointerType>(Ty)->getPointeeType(); + break; + case Type::LValueReference: + case Type::RValueReference: + T = cast<ReferenceType>(Ty)->getPointeeType(); + break; + case Type::MemberPointer: + T = cast<MemberPointerType>(Ty)->getPointeeType(); + break; + case Type::ConstantArray: + case Type::IncompleteArray: + // Losing element qualification here is fine. + T = cast<ArrayType>(Ty)->getElementType(); + break; + case Type::VariableArray: { + // Losing element qualification here is fine. + const VariableArrayType *VAT = cast<VariableArrayType>(Ty); + + // Unknown size indication requires no size computation. + // Otherwise, evaluate and record it. + if (auto Size = VAT->getSizeExpr()) { + if (!CSI->isVLATypeCaptured(VAT)) { + RecordDecl *CapRecord = nullptr; + if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { + CapRecord = LSI->Lambda; + } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { + CapRecord = CRSI->TheRecordDecl; + } + if (CapRecord) { + auto ExprLoc = Size->getExprLoc(); + auto SizeType = Context.getSizeType(); + // Build the non-static data member. + auto Field = + FieldDecl::Create(Context, CapRecord, ExprLoc, ExprLoc, + /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr, + /*BW*/ nullptr, /*Mutable*/ false, + /*InitStyle*/ ICIS_NoInit); + Field->setImplicit(true); + Field->setAccess(AS_private); + Field->setCapturedVLAType(VAT); + CapRecord->addDecl(Field); + + CSI->addVLATypeCapture(ExprLoc, SizeType); + } + } + } + T = VAT->getElementType(); + break; + } + case Type::FunctionProto: + case Type::FunctionNoProto: + T = cast<FunctionType>(Ty)->getReturnType(); + break; + case Type::Paren: + case Type::TypeOf: + case Type::UnaryTransform: + case Type::Attributed: + case Type::SubstTemplateTypeParm: + case Type::PackExpansion: + // Keep walking after single level desugaring. + T = T.getSingleStepDesugaredType(Context); + break; + case Type::Typedef: + T = cast<TypedefType>(Ty)->desugar(); + break; + case Type::Decltype: + T = cast<DecltypeType>(Ty)->desugar(); + break; + case Type::Auto: + T = cast<AutoType>(Ty)->getDeducedType(); + break; + case Type::TypeOfExpr: + T = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType(); + break; + case Type::Atomic: + T = cast<AtomicType>(Ty)->getValueType(); + break; + } + } while (!T.isNull() && T->isVariablyModifiedType()); +} + /// \brief Build a sizeof or alignof expression given a type operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, @@ -3763,6 +3885,20 @@ Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind)) return ExprError(); + if (T->isVariablyModifiedType() && FunctionScopes.size() > 1) { + if (auto *TT = T->getAs<TypedefType>()) { + if (auto *CSI = dyn_cast<CapturingScopeInfo>(FunctionScopes.back())) { + DeclContext *DC = nullptr; + if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) + DC = LSI->CallOperator; + else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) + DC = CRSI->TheCapturedDecl; + if (DC && TT->getDecl()->getDeclContext() != DC) + captureVariablyModifiedType(Context, T, CSI); + } + } + } + // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. return new (Context) UnaryExprOrTypeTraitExpr( ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd()); @@ -13158,120 +13294,7 @@ bool Sema::tryCaptureVariable( QualType QTy = Var->getType(); if (ParmVarDecl *PVD = dyn_cast_or_null<ParmVarDecl>(Var)) QTy = PVD->getOriginalType(); - do { - const Type *Ty = QTy.getTypePtr(); - switch (Ty->getTypeClass()) { -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_TYPE(Class, Base) -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) -#include "clang/AST/TypeNodes.def" - QTy = QualType(); - break; - // These types are never variably-modified. - case Type::Builtin: - case Type::Complex: - case Type::Vector: - case Type::ExtVector: - case Type::Record: - case Type::Enum: - case Type::Elaborated: - case Type::TemplateSpecialization: - case Type::ObjCObject: - case Type::ObjCInterface: - case Type::ObjCObjectPointer: - case Type::Pipe: - llvm_unreachable("type class is never variably-modified!"); - case Type::Adjusted: - QTy = cast<AdjustedType>(Ty)->getOriginalType(); - break; - case Type::Decayed: - QTy = cast<DecayedType>(Ty)->getPointeeType(); - break; - case Type::Pointer: - QTy = cast<PointerType>(Ty)->getPointeeType(); - break; - case Type::BlockPointer: - QTy = cast<BlockPointerType>(Ty)->getPointeeType(); - break; - case Type::LValueReference: - case Type::RValueReference: - QTy = cast<ReferenceType>(Ty)->getPointeeType(); - break; - case Type::MemberPointer: - QTy = cast<MemberPointerType>(Ty)->getPointeeType(); - break; - case Type::ConstantArray: - case Type::IncompleteArray: - // Losing element qualification here is fine. - QTy = cast<ArrayType>(Ty)->getElementType(); - break; - case Type::VariableArray: { - // Losing element qualification here is fine. - const VariableArrayType *VAT = cast<VariableArrayType>(Ty); - - // Unknown size indication requires no size computation. - // Otherwise, evaluate and record it. - if (auto Size = VAT->getSizeExpr()) { - if (!CSI->isVLATypeCaptured(VAT)) { - RecordDecl *CapRecord = nullptr; - if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) { - CapRecord = LSI->Lambda; - } else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { - CapRecord = CRSI->TheRecordDecl; - } - if (CapRecord) { - auto ExprLoc = Size->getExprLoc(); - auto SizeType = Context.getSizeType(); - // Build the non-static data member. - auto Field = FieldDecl::Create( - Context, CapRecord, ExprLoc, ExprLoc, - /*Id*/ nullptr, SizeType, /*TInfo*/ nullptr, - /*BW*/ nullptr, /*Mutable*/ false, - /*InitStyle*/ ICIS_NoInit); - Field->setImplicit(true); - Field->setAccess(AS_private); - Field->setCapturedVLAType(VAT); - CapRecord->addDecl(Field); - - CSI->addVLATypeCapture(ExprLoc, SizeType); - } - } - } - QTy = VAT->getElementType(); - break; - } - case Type::FunctionProto: - case Type::FunctionNoProto: - QTy = cast<FunctionType>(Ty)->getReturnType(); - break; - case Type::Paren: - case Type::TypeOf: - case Type::UnaryTransform: - case Type::Attributed: - case Type::SubstTemplateTypeParm: - case Type::PackExpansion: - // Keep walking after single level desugaring. - QTy = QTy.getSingleStepDesugaredType(getASTContext()); - break; - case Type::Typedef: - QTy = cast<TypedefType>(Ty)->desugar(); - break; - case Type::Decltype: - QTy = cast<DecltypeType>(Ty)->desugar(); - break; - case Type::Auto: - QTy = cast<AutoType>(Ty)->getDeducedType(); - break; - case Type::TypeOfExpr: - QTy = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType(); - break; - case Type::Atomic: - QTy = cast<AtomicType>(Ty)->getValueType(); - break; - } - } while (!QTy.isNull() && QTy->isVariablyModifiedType()); + captureVariablyModifiedType(Context, QTy, CSI); } if (getLangOpts().OpenMP) { |