Commit a452d078 authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r258396:

------------------------------------------------------------------------
r258396 | abataev | 2016-01-21 04:54:48 -0800 (Thu, 21 Jan 2016) | 2 lines

Fix crash for typedefs for arrays of runtime bounds in Lambdas/Captured Statements, used in sizeof() expression only.

------------------------------------------------------------------------

llvm-svn: 259414
parent dc223e67
Loading
Loading
Loading
Loading
+137 −114
Original line number Diff line number Diff line
@@ -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());
@@ -13144,120 +13280,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) {
+33 −20
Original line number Diff line number Diff line
@@ -10,10 +10,23 @@ void *use = &used;
// CHECK: @cvar = global
extern "C" auto cvar = []{};

// CHECK-LABEL: define i32 @_Z9ARBSizeOfi(i32
int ARBSizeOf(int n) {
  typedef double (T)[8][n];
  using TT = double [8][n];
  return [&]() -> int {
    typedef double(T1)[8][n];
    using TT1 = double[8][n];
    return sizeof(T) + sizeof(T1) + sizeof(TT) + sizeof(TT1);
  }();
}

// CHECK-LABEL: define internal i32 @"_ZZ9ARBSizeOfiENK3$_0clEv"

int a() { return []{ return 1; }(); }
// CHECK-LABEL: define i32 @_Z1av
// CHECK: call i32 @"_ZZ1avENK3$_0clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1avENK3$_0clEv"
// CHECK: call i32 @"_ZZ1avENK3$_1clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1avENK3$_1clEv"
// CHECK: ret i32 1

int b(int x) { return [x]{return x;}(); }
@@ -21,8 +34,8 @@ int b(int x) { return [x]{return x;}(); }
// CHECK: store i32
// CHECK: load i32, i32*
// CHECK: store i32
// CHECK: call i32 @"_ZZ1biENK3$_1clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1biENK3$_1clEv"
// CHECK: call i32 @"_ZZ1biENK3$_2clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1biENK3$_2clEv"
// CHECK: load i32, i32*
// CHECK: ret i32

@@ -30,8 +43,8 @@ int c(int x) { return [&x]{return x;}(); }
// CHECK-LABEL: define i32 @_Z1ci
// CHECK: store i32
// CHECK: store i32*
// CHECK: call i32 @"_ZZ1ciENK3$_2clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1ciENK3$_2clEv"
// CHECK: call i32 @"_ZZ1ciENK3$_3clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1ciENK3$_3clEv"
// CHECK: load i32*, i32**
// CHECK: load i32, i32*
// CHECK: ret i32
@@ -43,8 +56,8 @@ int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
// CHECK: call void @_ZN1DC1Ev
// CHECK: icmp ult i64 %{{.*}}, 10
// CHECK: call void @_ZN1DC1ERKS_
// CHECK: call i32 @"_ZZ1diENK3$_3clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1diENK3$_3clEv"
// CHECK: call i32 @"_ZZ1diENK3$_4clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1diENK3$_4clEv"
// CHECK: load i32, i32*
// CHECK: load i32, i32*
// CHECK: ret i32
@@ -54,18 +67,18 @@ int e(E a, E b, bool cond) { [a,b,cond](){ return (cond ? a : b).x; }(); }
// CHECK-LABEL: define i32 @_Z1e1ES_b
// CHECK: call void @_ZN1EC1ERKS_
// CHECK: invoke void @_ZN1EC1ERKS_
// CHECK: invoke i32 @"_ZZ1e1ES_bENK3$_4clEv"
// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev"
// CHECK: call void @"_ZZ1e1ES_bEN3$_4D1Ev"
// CHECK: invoke i32 @"_ZZ1e1ES_bENK3$_5clEv"
// CHECK: call void @"_ZZ1e1ES_bEN3$_5D1Ev"
// CHECK: call void @"_ZZ1e1ES_bEN3$_5D1Ev"

// CHECK-LABEL: define internal i32 @"_ZZ1e1ES_bENK3$_4clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1e1ES_bENK3$_5clEv"
// CHECK: trunc i8
// CHECK: load i32, i32*
// CHECK: ret i32

void f() {
  // CHECK-LABEL: define void @_Z1fv()
  // CHECK: @"_ZZ1fvENK3$_5cvPFiiiEEv"
  // CHECK: @"_ZZ1fvENK3$_6cvPFiiiEEv"
  // CHECK-NEXT: store i32 (i32, i32)*
  // CHECK-NEXT: ret void
  int (*fp)(int, int) = [](int x, int y){ return x + y; };
@@ -74,7 +87,7 @@ void f() {
static int k;
int g() {
  int &r = k;
  // CHECK-LABEL: define internal i32 @"_ZZ1gvENK3$_6clEv"(
  // CHECK-LABEL: define internal i32 @"_ZZ1gvENK3$_7clEv"(
  // CHECK-NOT: }
  // CHECK: load i32, i32* @_ZL1k,
  return [] { return r; } ();
@@ -91,7 +104,7 @@ void staticarrayref(){
  }();
}

// CHECK-LABEL: define internal i32* @"_ZZ11PR22071_funvENK3$_8clEv"
// CHECK-LABEL: define internal i32* @"_ZZ11PR22071_funvENK3$_9clEv"
// CHECK: ret i32* @PR22071_var
int PR22071_var;
int *PR22071_fun() {
@@ -99,19 +112,19 @@ int *PR22071_fun() {
  return [&] { return &y; }();
}

// CHECK-LABEL: define internal void @"_ZZ1e1ES_bEN3$_4D2Ev"
// CHECK-LABEL: define internal void @"_ZZ1e1ES_bEN3$_5D2Ev"

// CHECK-LABEL: define internal i32 @"_ZZ1fvEN3$_58__invokeEii"
// CHECK-LABEL: define internal i32 @"_ZZ1fvEN3$_68__invokeEii"
// CHECK: store i32
// CHECK-NEXT: store i32
// CHECK-NEXT: load i32, i32*
// CHECK-NEXT: load i32, i32*
// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_5clEii"
// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_6clEii"
// CHECK-NEXT: ret i32

// CHECK-LABEL: define internal void @"_ZZ1hvEN3$_98__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} {
// CHECK-LABEL: define internal void @"_ZZ1hvEN4$_108__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} {
// CHECK-NOT: =
// CHECK: call void @"_ZZ1hvENK3$_9clEv"(%struct.A* sret %agg.result,
// CHECK: call void @"_ZZ1hvENK4$_10clEv"(%struct.A* sret %agg.result,
// CHECK-NEXT: ret void
struct A { ~A(); };
void h() {